[Tutor PyCZ] Livewires V - seznam a proměnné

geon geon na post.cz
Neděle Březen 5 21:49:26 CET 2006


Tomáš Bělonožník napsal(a):
> Ahoj,
> opět jsem se zasekl a potřeboval bych pomoct. Ke konci tutoriálu už
> totiž potřebných a nových věcí přibývá a nápověd rapidně ubývá. Sice
> se mi podařilo program napsat tak, aby jakž takž celý fungoval, ale je
> tam spousta malých chybiček, je to rozvleklý a úplně jiný než to mělo
> být. Vrátím se k počátku problému. Mám program, kde hráče posunovaného
> stisky kláves honí "robot" a když ho dožene, hráč prohrál. Měl bych
> přidělat další roboty. Autor tutoriálu dává rady:
>     *   Vytvořte prázdný list robots.
>     * Opakujte pro každého robota, kterého chceme:
>           o Přidejte robota do seznamu robotů.
>           o Vytvořte náhodně souřadnice místa, kde by se měl robot
> narodit. Nezapomeňte nastavit atribut srot na 0.
>           o Opakujte while "pokud se tento robot srazil s jiným":
>                 + Zkuste jiné místo.
>           o Vytvořte tělo robota a uložte ho do jeho atributu telo.
> Když jsem se to snažil dělat takto, třeba se mi i podařilo vyrobit pět
> robotích těl, ale pohybovalo se pouze jedno a ostatní nereagovaly ani
> na kontakt. Dejme tomu tedy, že mám tuto funkci pro tvorbu robotů:
> def vyrobRobota(pocet_opakovani, seznam):
>   
Nevím, proč zde předáváš funkci proměnné, které jsou lokální, tedy 
platné jen uvnitř funkce. Asi ti není pořád zcela zřejmý princip 
předávání proměnný a zaměňuješ ho s definicí proměnné na lokální úrovni.
Já bych to tedy spíše viděl takto (pokud ovšem nechceš z hlavního 
programu měnit počty Robotů, ale tos ty neměl v tomto smyslu použito):
def vyrobRobota():
    pocet_opakovani=0
    seznam=[]
...
...

return seznam  # seznam vrátit, aby nezůstal lokální a nezanikl při 
opuštění fce ..
>     robot = Robot()
>   
aha, tady bude ta hlavní chyba, robot přeci musí vzniknout pokaždý nový, 
čili? tato řádka patří do cyklu! proto ti to asi fungovalo jak 
popisuješ, že se hýbal jen jeden a o hodně rychleji
>     while pocet_opakovani < 5:
>   
Tohle ti nemůže fungovat, nikde tam nezvyšuješ proměnnou 
pocet_opakovani. A je lepší, pokud přesně znáš počet opakování , použít 
cyklus for, tedy např. for i in range(5): ....
>   
> 	# Budoucí souřadnice robota
>         robot.x=random.randint(8, 631)
>         robot.y=random.randint(8, 471)
>
>         # Část funkce zajišťující, že hráč a robot nezačnou na sobě.
>         robot_x_round = robot.x / 10
>         hrac_x_round = hrac.x / 10
>         robot_y_round = robot.y / 10
>         hrac_y_round = hrac.y / 10
>         while robot_x_round == hrac_x_round and robot_y_round == hrac_y_round:
>   
Tady (opět  - už jsem to jednou psal) se někdy vůbec nedostaneš z cyklu, 
protože uvnitř nikde neměníš proměnné z podmínky za while, tedy  
robot_x_round a robot_y_round. Pro větší přehlednost bych tyto proměnné 
použil jako atributy instance, tedy např. robot.roundx, ....
>             robot.x=random.randint(8, 631)
>             robot.y=random.randint(8, 471)
>             hrac.x=random.randint(8, 631)
>             hrac.y=random.randint(8, 471)
>   
Myslím, že pozice hráče by se měnit neměla ;-) , jak k tomu přijde, aby 
se teleportoval, když se na něm náhodou narodí robot :-)
>         seznam.append(robot)
>   
Zde to nevadí, ale obecně je lépe přidávat do seznamu, až když je vše 
hotové, tedy bych  seznam.append(robot) dal až za robot.telo=.....
>         robot.telo = box(robot.x-5,robot.y-5,robot.x+5,robot.y+5,
> filled=1, colour=Colour.dark_blue)    # Popis těla robota
>
>   
> Toto mi vytvoří seznam s pěti instancemi robot třídy Robot. Jak ale
> udělat, aby se v této funkci všichni hýbali?
> def posunRobota(hrac):
>     for robot in seznam:     #tahle řádka je tu navíc, tak jsem to zkoušel
>         if robot.x < hrac.x:
>             robot.x = robot.x + 5
>         elif robot.x > hrac.x:
>             robot.x = robot.x - 5
>         if robot.y < hrac.y:
>             robot.y = robot.y + 5
>         elif robot.y > hrac.y:
>             robot.y = robot.y - 5
>         move_to(robot.telo, robot.x, robot.y)
>         sleep(0.2)
>   
> Přijde mi, jako by si ti roboti v seznamu nedokázali pamatovat svoje
> .x a .y nebo spíš za toho robota, kterým se má hýbat, byl pokládán
> pořád jeden a ten samý, protože se hýbe mnohem rychleji než hráč. Tomu
> by nasvědčovalo i to, že jsem kdesi četl, že jména v Pythonu jsou
> prakticky jen odkazy na objekty.
>
>
>   
tak to jsem psal nahoře.

Dál již nečtu (snad někdo jiný) , ale jedna rada na závěr - možná to již 
znáš, ale možná ne - zkus na promptu zkoušet, po dokončení programu at 
po chybě nebo normálně, věci, o kterých si myslíš, že by měly nějak být 
- např. jestli v seznamu ní je pět členů a pro jednoho, zkusmo, jestli 
má atributy, co má mít ... apod. Při tomto způsobu práci já osobně si 
tyto proměnné, které jsou často schovány uvnitř funkcí globalizuji, 
protože po chybě se nalézáš v hlavní části programu a tam se lokální 
proměnné funkcí tváří, že neexistují.

Také by nebylo od věci vyzkoušet Debugger...  v IDLE menu Debugger  -  a 
pečlivě sledovat proměnné, jestli se ti mění jak mají ;-)

Ahoj!

-- 
geon
Vyjímka je pravidlo. Rekurzivní.



Další informace o konferenci Tutor