Python: funkcie, range, vlastná hra
Funkcie
Príkazy print, int, input, len, ..., ktoré sme používali doteraz, majú
niečo spoločné. Pozrime sa na ne ako na stroje.
- Do stroja niečo vhodíme, spustíme ho,
- on niečo spraví,
- a nakoniec niečo vyhodí zo seba von.
Do príkazu int vhodíme hodnotu, napr. '10', prevedie ju na číslo a vrátí
nám hodnotu 10. Takýmto príkazom hovoríme funkcie. Funkcie majú vstup a
výstup, niečo berú ako argument na vstupe a vrátia hodnotu na výstupe
(návratová hodnota). Niektoré funkcie nemusia
mať argument, napr. input(), naopak print( 'a', 4, 10 ) má viac argumentov
(jednotlivé argumenty oddeľujeme čiarkou), ale zase žiadnu návratovú hodnotu.
Poznámka
To, že print nemá návratovú hodnotu nie je tak úplne pravda:
Návratová hodnota je None. Je to jediná možná hodnota dátového typu
NoneType. Len pre zaujímavosť, pre nás to teraz vôbec nie je
dôležité.
Dobrá správa je: Python umožňuje vytvoriť si vlastné funkcie! Slúži na to
príkaz def, znovu na konci obsahuje dvojbodku a nasleduje blok kódu (telo
funckie) odsadený vpravo, ktorý sa vykoná, ak túto funkciu zavoláme (to
znamená, použijeme ju v programe).
Prvý riadok sa nazýva hlavička funkcie. Určuje názov funkcie a parametry.
Medzi parametrom a argumentom je veľmi slabý rozdiel a často sa ich význam
zamieňa. Ak chceme byť presný, 'robot' a 'Adam' sú argumenty. who je
parameter. Ako auto zaparkuje na parkovisko, tak aj argument
zaparkuje na parameter, takže hodnota 'robot' (argument) sa uloží do
premennej who (parameter). Ešte inak: ak sa pozeráme zvnútra funkcie, vidíme
parametre. Ak sa pozeráme zvonka, vidíme argumenty.
Úloha 1
Napíšte funkciu print_max, ktorá vypíše maximálny prvok v zozname. Ak je
zoznam prázdny, vypíše túto informáciu. Napr:
Úloha 2
Pokúste sa v definícii funkcie "print_max" použiť funkciu max (ktorá je už
vstavaná v Pythone). Krátka ukážka ako funguje:
>>> max( [ 1, 2, 0 ] )
2
>>> max( 'dkrn' )
'r'
>>> max( [] )
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: max() arg is an empty sequence
Takže pozor na to, aby argumentom nebol prázdny zoznam, toto bude treba
otestovať ešte pred tým, ako sa zavolá funkcia max.
Čo ak by sme chceli aj my niečo vrátiť z našej vlastnej funkcie, nielen
vypisovať? Slúži na to slovíčko return:
def area( a, b ):
return a * b
print( area( 2, 3 ) )
print( area( 0, 10 ) + area( 10, 0 ) )
print( area( 1, area( 2, 3 ) ) ) # well, this is "volume"
Prvý riadok (po definícii funkcie area) zavolá area( 2, 3 ). Do premennej
a sa uloží hodnota 2, do b hodnota 3. Potom sa vyhodnotí a * b na
hodnotu 12, ktorá sa vráti spať a vykoná sa print( 12 ). Podobne si vieme
rozobrať aj posledný riadok:
print( area( 1, area( 2, 3 ) ) )print( area( 1, 6 ) )print( 6 )- Na obrazovke uvidíme text "6"
Úloha
Napíšte funkciu, ktorá vráti počet kladných čísel v zozname.
range
Ukážeme si jednu novú, užitočnú funkciu, hlavne v spojení s for ... in
cyklom. Volá sa range a môže brať jeden, dva, alebo aj tri argumenty. Vráti
špeciálnu hodnotu typu 'range', ktorú ale vieme konvertovať do zoznamu pomocou
funkcie list:
>>> list( range( 10 ) )
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> list( range( 0 ) )
[]
>>> list( range( 1 ) )
[0]
>>> list( range( 0, 10 ) )
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> list( range( 0, 0 ) )
[]
>>> list( range( 3, 5 ) )
[3, 4]
>>> list( range( -3, 3 ) )
[-3, -2, -1, 0, 1, 2]
>>> list( range( -3, 3, 2 ) )
[-3, -1, 1]
>>> list( range( 0, 10, 1 ) )
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> list( range( 0, 10, 3 ) )
[0, 3, 6, 9]
>>> list( range( 10, 0, -3 ) )
[10, 7, 4, 1]
range(a, b, c) vygeneruje čísla od a (vrátane) do b (vynímajúc) s
rozdielmi c medzi každými dvomi číslami. Ak použijeme iba dva argumenty, c
sa nastaví automaticky na jednotku. A ak iba jeden, a sa nastaví na nulu.
Ak ale použijeme túto funkciu s konštrukciou for ... in, môžme vynechať
konvertovanie cez list, lebo vie pracovať aj s špeciálnou hodnotou typu
'range', akú vracia funkcia range.
for spolu s range častokrát dokáže nahradiť cyklus while a lepšie sa s
ním pracuje. Ak si spomenieme napr. na náš program kresliaci trojuholníky,
teraz by sme samotné kreslenie (načítanie veľkosti na vstupe zostáva rovnako)
vedeli napísať nasledovne:
A nakresliť opačný trojuholník (so špičkou na vrchu) by bolo podobne jednoduché:
Úloha
Napíšte program, ktorý sa spýta užívateľa na dve čísla. Tie budú znamenať
veľkosť strán obdĺžnika. Potom pomocou for ... in range vykreslite takýto
obdĺžnik. Pre veľkosti 4 a 6 by mal vyzerať takto:
Labyrint
Poďme si spolu naprogramovať jednoduchú hru. Už máme nejaké skusenosti s programovaním, takže pokým sa trochu obmedzíme v našich nárokoch na kvalitu, zvládneme to ľavou zadnou.
Cieľom hry bude dostať sa v labyrinte do cieľa. Labyrint budeme kresliť podobne ako v poslednej úlohe, mriežky (#) budú označovať steny, medzery ( ) voľné políčka. Cieľ označíme ako písmeno X a našu postavičku O. V každom kole vyzveme používateľa aby zadal jedno z písmenok:
- w - krok hore
- a - krok vľavo
- s - krok dole
- d - krok vpravo
- q - ukončiť hru
Na začiatku si zadefinujeme všetky tieto konštanty, teda premenné, ktoré sa nebudú meniť. V Pythone je zvykom písať ich názvy veľkými písmenami.
Hracie pole si ukladáme ako zoznam textových reťazcov - riadkov. Výška poľa je
počet riadkov, ktorý vieme zistiť funkciou len. Tiež ju použijeme na zistenie
šírky, t.j. počet stĺpcov, ktorý sa rovná dĺžke každého (a teda napr. prvého)
riadku. Na začiatku hráča umiestnime do ľavého dolného rohu. Pamätajme, že
indexy začínajú nulou. X-ová súradnica je horizontálna (zľava doprava), y-ová
je vertikálna (zhora dolu).
Teraz si napíšeme funkciu, ktorá vykreslí hracie pole aj s hráčom. Funkcia bude
mať dva parametre: aktuálne súradnice hráča. Budeme prechádzať pomocou
vnoreného for cyklu celé hracie pole po riadkoch, ak na danom políčku stojí
hráč, vykreslíme jeho znak, inak vykreslíme políčko z hracieho pola. Doteraz
sme print používali tak, že na konci výstupu vždy vložil znak konca riadku
(akoby stlačil na konci riadku Enter). To je jeho prednastavené správanie.
Teraz ale nechceme aby bolo každé políčko na svojom vlastnom riadku, chceme ich
vykresliť hneď vedľa seba. Preto použijeme špeciálny (optional) parameter
end, kde mu nastavíme znak, ktorý má vykresliť na konci výstupu. Skúste si
v shelli spustiť napr. print( 'afad', end='###' ). My naozaj nechceme vypísať
medzi políčkami nič, preto nastavíme tento parameter na prázdny text.
Napíšeme si ešte jednu dôležitú funkciu. Bude načítavať vstup od užívateľa a posúvať hráča. Ako vstup zoberie tiež súradnice hráča a vráti 3 hodnoty: nové súradnice po posune a logickú hodnotu, či sa má hra ukončiť. Viac ako jednu hodnotu sme doteraz nevrátili v žiadnej funkcii, ale je to jednoduché:
Teraz implementujeme hlavnú logiku. Načítať viacero hodnôt z funkcie je rovnako jednoduché.
Tak, a hra je hotová :) Nezabudnite, že príkaz input vždy čaká na stlačenie
klávesy Enter, takže sa hra nedá ovládať plynule ako sme zvyknutí, len
držaním "w" "a" "s" "d". To by sme mohli ešte vylepšiť, no najbližšie si už
postavíme svojho prvého robota a rozpohybujeme ho Pythonom! Zároveň
si postupne budeme ukazovať všeliaké nové užitočné príkazy.

Úloha
Ak ešte máte chuť trochu popracovať na našej hre, tu je niekoľko návrhov:
- Vytvorte viacero rôznych bludísk, nechajte hráča, aby si z nich vybral.
- Pridajte počítadlo krokov. Čím viac krokov hráč spraví pokým sa dostane do cieľa, tým nižšie bude jeho skóre, ktoré na konci hra vypíše.
- Do bludiska pridajte diamanty (napr. znak bodky "."), tie bude hráč zbierať, takže po prejdení políčka s diamantom, diamant na ňom už nesmie zostať! Pozbierané diamanty hráčovi zvyšujú skóre.
- Do hry môžete pridať dvere "D" a kľúč "K". Keď hráč zoberie kľúč, dvere sa mu otvoria a bude môcť prejsť do cieľa.