Na konci dnešní lekce budete mít program, který vás nebo kohokoliv jiného bude zkoušet z násobilky. V průběhu tvorby se naučíme mimo jiné generovat náhodná čísla a pamatovat si je, ptát se a zpracovávat odpovědi od uživetele, rozhodovat, jestli je něco pravda nebo nepravda, opakovat věci několikrát dokola.
Co potřebujete znát
Rozmyslíme si to
Když začínáte přemýšlet o tom, že napíšete nějaký program, je užitečné se zamyslet nad tím, co se má stát, když se program spustí. V našem případě by to být něco jako toto:
Kolik je 6 x 7? 49
Ne, lituji, správná odpověď je 42.
Kolik je 3 x 2? 6
Ano - to je dobře. A tak dále několik dalších otázek...
Kolik je 5 x 9? 45
Ano - to je dobře.
Zeptal jsem se 10 x. 7 x jsi odpověděl správně.
Výborně!
Máme tu několik věcí, které musí program umět:
- Náhodně volit čísla
- Ty čísla vytisknout jako příklad
- Vypočítat správnou hodnotu (zatím netisknout)
- Zjistit odpověď od člověka, který program používá
- Zjistit, jestli je správná nebo ne
- Zobrazit zprávu "to je dobře" nebo "to je špatně"
- Sledovat, kolikrát jsme již odpovídali
- Zeptat se celkem řekněme 10 otázek a pak zastavit
- Zobrazit poslední zprávu o tom, jak jste si vedli
To je docela dost věcí k probrání, ale většina z nich je docela jednoduchá. Budeme dělat jednu po druhé. Je zde spousta úkolů. Nemusíte mi je všechny posílat, ale rozhodně všechny si vyzkoušejte a hrajte si s nimi! Jeden malý fungující program je důležitější než tuny teorie. Nepřeskakujte výzvy! Dokud vám nebudou fungovat, nechoďte dále. Neváhejte se zeptat v Poradně nebo v Konferenci Python, pokud nebude cokoliv jasného.
Tisk několika věci za sebou
Chceme-li vytisknout více věcí za sebou v jednom řádku, použijeme čárku na oddělení jednotlivých věcí mezi sebou. Příklad:
>>> cena=1000
>>> print "Cena výrobku byla ", cena, "Kč."
Příkaz print
se používá, když chcete přimět počítač, aby něco vytisknul. Dosud jsme to nepotřebovali, protože tiskne odpověď automaticky jen když jsme v promptu a když je to věc, která se dá vypočítat. A to v tomto případě není. V programech musíme print
k tisku používat vždy.
Náhodná čísla
Začneme s první položkou na seznamu: Náhodné generování čísel. Zkuste se Pythona zeptat toto a sledujte co říká:
>>> import random # To je kouzlo; viz níže.
>>> random.randint(10,15)
Co myslíte, že randint
dělá? Zkuste opakovat poslední řádku několikrát, dokud si nebudete jistí, jak se chová. Ten křížek (#) a vše co je za tím psát nemusíte, to je tzv. komentář a je jen pro vás, jen pro komentování kódu. Pro Python to neznamená vůbec nic, nemá to žádnou funkci, python komentáře zvesela ignoruje. První řádka je důležitá. Musíte ji dát na začátek každého programu, který využívá randint
. Umožňuje vám importovat neboli vtáhnout do vašeho programu dodatky k čistému Pythonu. Stejně jako to vkládáte do programu, měli byste to napsat i na promptu (jako zde), pokud budete používat náhodná čísla. Jinak nebude Python rozumět, co po něm chcete.
Výzva: Vytvořte program, který bude tisknout: Kolik je 7 x 2 ?
, kde ty 2 čísla (7 i 2) jsou náhodně generovány mezi 1 a 10 (včetně).
Otázky a odpovědi
OK, tak teď víme jak přimět Python, aby vytiskl otázku. Není to ale moc k užitku, pokud bychom nemohli dostat odpověď od člověka používající program. To ale naštěstí můžeme. Zkuste toto a sledujte co se bude dít:
>>> print input('Zadejte cislo: ')
Pokud zadáte něco jiného než číslo, Python ohlásí chybu, protože chce jen číslo, třeba i desetinné, ale číslo. A také: pokud nechcete, aby se někdy vyskytovaly místo českých písmenek při běhu programu divné znaky, používejte zatím cestinu bez hacku a carek. Místo 'Zadejte cislo' můžete samozřejmě zadat i jiný text, libovolný text.
Výzva: Ať se Python zeptá na dvě čísla a vytiskne jejich součet. Nápověda: print input('Zadej prvni cislo ') + ......
Výzva: Zde začínáte s vaším hlavním programem na testování násobilky. Napište krátký program, který zobrazí příklad součinu dvou náhodných čísel a pak požádá uživatele o odpověď (Nebude tedy výsledek počítat ani tisknout). Např. Kolik je 10 * 7?
To by mělo být záležitostí kombinace dvou věcí, které jste již dělali. Nedělejte si zatím starosti s tím, jestli uživatel odpoví správně nebo ne. Program si uložte, abyste o něj nepřišli - budete ho znovu potřebovat.
Pamatujeme si čísla
Dobře, takže teď se začneme starat o to, jak má program zjistit, jestli je uživatelova odpověď správná. To je důmyslnější než cokoliv, co jsme dosud dělali, protože my potřebujeme náhodné číslo použít dvakrát: jednou, když tiskneme příklad součinu a podruhé, když budeme zjišťovat, jestli je odpověď správná. Důležitý princip: Pokud píšete program a potřebujete něco použít dvakrát a více, dejte tomu nějaké jméno. Jména jsme již probírali, tak jen krátkou připomínku. Věcem dáváme jména použitím znaku =, a pak můžete používat jméno místo samotné věci, kterou jsme pojmenovali:
>>> neco=1234 # do promenne 'neco' zapis 1234
>>> 5*neco
6170
A co dělá toto?
>>> odpoved = input('Zadejte cislo: ')
>>> print '2 x', odpoved, '=', 2*odpoved
Výzva: Napište program, který vytvoří náhodné číslo a vytiskne ho 5 krát. (To není to samé jako vytištění 5 různých náhodných čísel). Budete muset dát náhodnému číslu jméno neboli ho budete muset uložit do proměnné, kterou pak budete teprve tisknout.
Výzva: Otevřete si svůj program na testování násobilky. Změňte ho tak, aby náhodná čísla ukládal nejprve do proměnných a teprve tyto proměnné potom používal při tisku. Stejně tak uživatelova odpověď musí přijít nejdříve do proměnné. Váš program tedy umí již následující:
- Zvolit dvě náhodná čísla od 1 do 10.
- Zobrazit příklad na násobení.
- Zeptat se na odpověď.
- Vytisknout, kolik to má být.
První tři věci jsme již dělali. Jediná nová věc je ta poslední. Výsledek, tedy kolik to má vyjít, uložte také do proměnné, např. vysledek=prvniCislo*druheCislo
a teprve potom vytiskněte. Program znovu uložte!
Dobře nebo špatně?
Program, který jste právě napsali, by se asi mohl používat na zkoušení někoho z násobilky, ale bude hloupé chtít po člověku, aby si sám kontroloval výsledky; to je právě ta nudná práce, kterou počítače zvládají dobře. Takže v dalším stupni necháme stroj prověřit, jestli odpověď, kterou od uživatele dostal, je správná, namísto toho, že jen napíšeme, kolik to mělo být a nechali na uživateli, ať si to zhodnotí sám. Abychom toho dosáhli, potřebujeme novou - a velmi důležitou - myšlenku.
If... (Když...)
Napište program, který vypadá jako tento a spusťte ho. (Mezery na začátku některých řádek jsou důležité!)
cislo=input('Zadej cislo: ')
if cislo < 10:
print 'Cislo je mensi nez 10.!'
else:
print 'Cislo je vetsi nebo rovno 10!'
Příkaz dělá toto: Pokud (if) bude cislo menší než 10, provede jen to první print, jinak (else), tedy pokud bude cislo větší nebo rovno 10, provede jen to druhé print. Mnohokrát si to vyzkoušejte! Důvod, proč záleží na mezerách na začátku řádku je ten, že Python je používá při rozhodování, kolik toho z vašeho programu patří do if
. Tomu odsazenému vnitřku říkáme tělo. Řekněme, že napíšete
cislo=input('Zadej cislo: ')
if cislo > 1000:
print 'Och!'
print 'Bink!'
Pokud zadáte číslo menší než 1000, podmínka cislo>1000
nebude splněna, a proto se její tělo print 'Och!'
neprovede (nevytiskne) a pokračuje se nejbližším příkazem za ním. Vytiskne se tedy jen Bink!
, protože řádka print 'Bink!'
nepatří do těla if
. Ale když by řádka print 'Bink!'
měla na začátku mezery, jako má řádka print 'Och!'
, tak by to bylo součástí těla if
, a nevytisklo by se vůbec nic. Je to velmi důležitá myšlenka, proto si s ní větší než malou chvíli pohrajte, abyste ji porozuměli. Příkaz bychom mohli číst také takto: Pokud je cislo větší než 1000, tak vytiskni 'Och' a pokračuj pak za vnitřkem (tělem) if, tedy vytiskni ještě 'Bink!'. Pokud ale číslo bude menší nebo rovno 1000, vnitřku (těla) if si vůbec nevšímej a pokračuj hned prvním příkazem za ním - vytiskne se tedy jen 'Bink!'.
Většina programovacích jazyků si nevšímá, jestli jsou na začátku řádku nějaké mezery. To znamená, že musí řešit podobný problém jinou cestou. Obvykle potřebují nějaké endif
na konci if
, nebo trvají na tom, že vše uvnitř if
musí být ohraničeno nějakými druhy závorek. Pythonýrský způsob je snadnější číst. Prostředí IDLE i PSPad toto podporuje. To znamená, že když za : dáte Enter, tak editor sám odsadí pár mezer od začátku. Zpětný návrat na začátek řádku musíte udělat sami, pomocí Mazání.
Výzva: Napište program, který se vás zeptá na číslo a pak vytiskne různé hlášky v závislosti na tom, jestli je číslo větší nebo menší než 100. My samozřejmě pro náš testovací program nepotřebujeme znát, jestli číslo, které jste napsali, je větší než správná odpověď; my chceme vědět, jestli je stejné. Možná byste napsali if neco = necojineho:
a tak dále a očekávali, že to bude správně; nicméně , aby zabránil kolizím mezi použitím = ve smyslu "je stejné jako" a použitím = ve smyslu "je jméno pro", používá dva různé symboly pro tyto dva smysly. Již jsme si ukazovali, že = značí "je jméno pro" a tak tedy "je stejné jako" musí být něco jiného. A opravdu v Pythonu se "je stejné jako" píše se dvěma rovnítky, tedy takto: ==
. Použití jediného =
vede k chybě. Tedy např.:
if cislo==1000:
print "cislo je tisic"
Výzva: Změňte prográmek, který jste před chvilkou napsali a který testoval, jestli číslo je větší než 100 tak, aby testoval jestli číslo je rovno 100. Nyní by již neměl být problém předělat náš testovací program tak, aby tiskl "ano!" nebo "ne!" podle toho, jestli vaše odpověď bude správná nebo ne. Navíc, pokud odpovíme špatně, vytiskne jak to má být správně. V tomto okamžiku máme tedy program, který vás otestuje na jeden příklad na násobení a pak skončí. Děláme pokroky!
Znovu a znovu a znovu
Nyní se budeme snažit, aby nás program vyzkoušel z deseti příkladů a teprve potom skončil. Možná si pamatujete cyklus for
z 1. lekce. Ať ano nebo ne, tady je příklad, jak ho použít. Napište krátký program:
for x in 1, 2, 3, 4, 5, 6:
print 'x =', x
Dáváte si stále pozor na to, co znamenají mezery na začátku řádku? Mělo by se vytisknout 6 čísel, od 1 do 6 včetně. Celému tomu říkáme cyklus nebo smyčka a tomu všemu uvnitř (co je odsazené) tělo. Cyklus for dělá toto: při prvním průchodu se do x zapíše 1 (protože je na prvním místě v seznamu čísel) a provede se tělo, tedy tisk. Pak se Python vrátí na začátek smyčky, na příkaz for a zjišťuje, jestli tam má ještě něco k dělání. A má - ještě tam je dalších 5 čísel. Vezme tedy 2, uloží do x a opět provede tisk. A tak dále až skončí u 6, kterou vytiskne. Pak se opět vrátí na začátek for a zjistí, že 6 byla poslední, takže již nic dalšího netiskne a skončí (= pokračuje nejbližším dalším příkazem). Podobného výsledku můžeme také dosáhnout vnitřní funkcí range()
:
for x in range(6):
print 'x =', x
Takto dostanete také šest čísel, ale tentokrát od 0 do 5 včetně. Místo 6 vyzkoušejte i jiná čísla.
Výzva: Pokud se vám to podařilo, najděte svůj testovací program a udělejte něco podobného tak, že se to celé (kromě první řádky, kde je import) bude opakovat 10 krát. Tip: Asi budete potřebovat odsadit několik řádek, které musí být uvnitř v cyklu for. Používejte na to Tabulátor a ne Mezerník.
Kdo to počítá?
Před chvílí jsem si stěžoval, že náš program nutí člověka, který ho používá, k tomu, aby si sám kontroloval své odpovědi. To jsme již zvládli, ale nyní si stále ještě uživatel musí počítat správné odpovědi. Počítač by měl být schopný umět i toto. Tady je malý prográmek na vyzkoušení. Nemá toho mnoho společného s testerem násobilky, ale snad takto jednodušeji pochopíte, jak dále postupovat.
pocet=0
pocet=pocet+1
print 'Celkem je v pocet: ', pocet, 'kousku.'
pocet=pocet+1
print 'Celkem je v pocet: ', pocet, 'kousku.'
Jak může být pocet rovno pocet+1? To samozřejmě nejde. Tu řádku si musíme představit rozloženou v čase: vypočítej kolik je pocet+1; a teprve pak výsledek ulož zpětně do pocet. Výše uvedený příklad by šel řešit také tímto způsobem:
pocet=0
for x in 1,2:
pocet=pocet+1
print 'Celkem je v pocet: ', pocet
Výše jsem říkal, že "jménům" říkáme "proměnné". Nyní jste objevili proč: věci, které takto pojmenováváme, se mohou měnit, se mohou proměňovat. V programu nahoře pocet
na začátku je 0; pak 1, pak 2. V tomto případě promennou x vůbec nepoužíváme, máme ji tam jen pro pořádek. OK. Zpět k testeru násobilky. Přidejte následující řádky do vašeho testeru násobilky. Musíte ale vyřešit, kam to tam dát. Některé řádky budou potřebovat na začátek vložit několik mezer, aby zarovnání přesně sedělo s těly for nebo if.
dobre = 0
spatne = 0
dobre = dobre + 1
spatne = spatne + 1
print 'Mate', dobre, 'spravnych odpovedi a', spatne, 'spatnych.'
A to je vše!
Zde byste měli mít funkční program. Udělali jste velký kus práce. Říká se, a zkušenost to potvrzuje, že program není nikdy hotov, nikdy dokonalý. S tím je třeba se smířit. Je toho zde spoustu k vylepšení.
Vylepšujeme program
Nemáte-li ještě programu dost, mohli byste vyzkoušet následující:
-
Vylepšete vzhled. Je nehezké, když otázka a uživatelova odpověď je na různých řádkách, a že je tam několik zbytečných mezer. Již jsme si říkali, že čárka u příkazu print způsobí, že se další věc tiskne na tu samou řádku. Funguje to i na konci, např.
print a,'+',b,'=',
. - Nastavujeme obtížnost. Někteří lidé zvládají počty velmi dobře. Pro ně je pak nudné nechat se zkoušet z čísel od 1 do 10. Někdo ale je zase na tom s počítám velmi špatně, takže to pro něho může být těžké. Je zřejmé, že nebude těžké změnit program tak, aby používal větší nebo menší čísla. (Koukněte na program a ujistěte se, že víte jak na to.) Snad by bylo zajímavější, kdyby program po každé správné odpovědi trochu "přitvrdil" a po každé špatné odpovědi trochu "ubral" na obtížnosti. (Budete asi potřebovat více jak 10 otázek, aby toto fungovalo dobře.)
- Nastavujeme délku. Také by šlo udělat nějaké rychlo-zkoušení, tedy třebas jen 4 otázky. A jeden superdlouhý test se 100 otázkami, abychom se ujistili, jak dlouho dokáže uživatel zůstat bdělý. Ať se tedy program zeptá, kolik otázek chcete a pak tolik otázek položí. Na to budete potřebovat řady - příkaz range().
Úkol
Zašlete mi výsledek vašeho snažení. Těším se na to! Úkoly neposílejte mailem, ale odevzdávejte přes webové rozhraní zde na Programujte (vpravo nahoře po přihlášení). Kdo chce za 1, musí v souladu s pravidly, odevdzat něco navíc. Zde v této lekci např. něco z Vylepšujeme program. Toto pravidlo platí i ve všech dalších lekcích.