Programování pro hračičky/Opičky/Lekce 7

Jak používat klasifikační nálepkuTato stránka je součástí kurzu:
středoškolská
Příslušnost: skupinová

Poté, co jsme se naučili řídit opičku v závislosti na splnění různých podmínek, nejspíše leckterého majitele opičky napadlo, jak by bylo pěkné, aby opička mohla nejenom rozpoznat, zda je podmínka splněna, nýbrž dokonce počkat, než bude nějaká podmínka splněna. Je sice pěkné, že si opička umí vzít sušenku a najíst se, pokud se na stole u Josefa nachází sušenka, ale nebylo by daleko lepší, aby v případě, že sušenka na stole není, dokázala v místnosti počkat, dokud se sušenka na stole neobjeví, a pak si ji vzít a sníst? Bystrý čtenář tuší, že když se takhle návodně ptáme, tak to opička skutečně dokáže:[1]

  dokud nevidíš sušenku
    tvař se jako opička čekající až někdo řekne nahlas slovo sušenka
  potom
  vem sušenku
  jez sušenku

Když opička při vykonávání programu narazí na slovo dokud, tak otestuje podmínku, a pokud je splněna, vykoná postupně všechny následující příkazy až do slova potom (nebo do konce programu, pokud v němž už slovo potom nenajde), a pak se opět vrátí ke slovu dokud. To znamená, že skutečně pořád dokola koná příkazy umístěné mezi dokud a potom tak dlouho, dokud je splněna podmínka. Programátoři takovou konstrukci poměrně logicky nazývají cyklus, a toto označení budeme používat i my.

Takzvané tělo cyklu, tedy to, co se má konat stále dokola, dokud je podmínka splněna, tvoří v našem prvním příkladu jediný příkaz tvař se jako opička čekající až někdo řekne nahlas slovo sušenka.[2] Tím opička nejen čeká, ale také napovídá případným hráčům, kteří do místnosti přijdou, jak by jí mohli pomoci — vyslovit klíčové slovo, po němž Josef vykouzlí na stůl nové sušenky, protože opička sama mluvit neumí. Jakmile se na stole objeví sušenka, přestane být pravda, že nevidíš sušenku, a opička pokračuje ve vykonávání příkazů od slova potom, tedy vezme si jednu sušenku a začne ji jíst.

Co když ale jedna sušenka nebude stačit na to, aby se opička nasytila? Josef vykouzlí vždy náhodné množství sušenek, možná jich je mnohem více a byla by škoda je nechat jen tak ležet. Opička tedy může poté, co se na stole objevily sušenky, zahájit další cyklus, jímž si postupně vezme a začne jíst všechny sušenky:

  dokud nevidíš sušenku
    tvař se jako opička čekající až někdo řekne nahlas slovo sušenka
  potom
  dokud vidíš sušenku
    vem sušenku
    jez sušenku

Co když ale opička vůbec nemá hlad? Nemůže pro ni být přejídání nebezpečné? Inu, můžeme přece použít podmínku máš hlad, abychom zajistili, že opička se začne shánět po sušence jen v případě, že má hlad. A tuto podmínku můžeme také použít v cyklu (pak bude ovšem stačit vzít vždy jen jednu sušenku, protože opička následně opět od začátku prověří, zda nemá hlad, a v případě potřeby začne shánět další sušenku):

  dokud máš hlad
    dokud nevidíš sušenku
      tvař se jako opička čekající až někdo řekne nahlas slovo sušenka
    potom
    vem sušenku
    jez sušenku
  potom
  tvař se sytě

Na tomto příkladu vidíme, že jak cyklus s podmínkou máš hlad, tak cyklus s podmínkou nevidíš sušenku má své ukončovací slovo potom. V našem přehledném zápisu rozpoznáme podle odsazení řádků, že potom na řádku 4 patří k podmínce na řádku 2, zatímco potom na řádku 7 patří k podmínce na řádku 1. Opičce ovšem nemůžeme zadat příkazy takto, ale zadáváme jí jednu dlouhou posloupnost příkazů, takže z jejího hlediska můžeme přesněji říci, že slovo potom patří vždy k té nejbližší minulé podmínce, k níž zatím nepatří žádné slovo potom. Když opička narazí na potom, které vidíme na řádku 4, přiřadí je k podmínce nevidíš sušenku, a tím pro sebe ukončí tento malý cyklus, a když pak narazí na další potom, přiřadí je k podmínce máš hlad, a tím uzavře velký vnější cyklus.

Pokud jsme porozuměli těmto třem příkladům, pak jsme vybaveni k základnímu využití cyklů: umíme napsat cyklus trvající, dokud něco není, i cyklus trvající, dokud něco je, umíme zařadit dva cykly za sebe i vnořit dva cykly do sebe, a také umíme cyklus správně zakončit slovem potom. Pokud máme dobrodružného ducha, vlastně ani nemusíme číst tuto lekci dál, protože všechno, co bychom se dočetli dále, si můžeme sami experimentujíce odhalit.

Cykly ve složitějších strukturách

editovat

Cykly můžeme samozřejmě kombinovat s podmíněnými příkazy. Můžeme například spustit cyklus jen v případě, že byla splněna nějaká jiná podmínka, tedy vnořit cyklus do podmíněného příkazu:

  pokud vidíš vodu
    dokud máš žízeň
      pij vodu
    potom
    tvař se napitě

Anebo se můžeme uvnitř spuštěného cyklu ptát, zda byla splněna nějaká jiná podmínka, tedy vnořit podmíněný příkaz do cyklu:

  dokud máš hlad
    pokud máš jídlo
      jez jídlo
    jinak
      pokud vidíš jídlo
        vem jídlo
        jez jídlo
      potom
    potom
  potom
  tvař se sytě

Každopádně ovšem, stejně jako když vnořujeme podmíněný příkaz do podmíněného příkazu nebo cyklus do cyklu, musíme dávat dobrý pozor, ke které podmínce se vztahuje ukončovací slovo potom, případně přepínací slovo jinak.

Stejně jako v případě složitějších konstrukcí z podmíněných příkazů, můžeme i složitější konstrukce s cykly rozložit do více podprogramů, které nám umožní přehledně a odděleně zapsat ucelené části složitého úkolu (potažmo usnadní hospodaření se vzájemně se pletoucími potom):

hamham <1>:
  jez <1>
  dokud máš <1>
    tvař se žravě
najezse:
  dokud máš hlad
    pokud máš jídlo
      hamham jídlo
    jinak pokud vidíš jídlo
      vem jídlo
      hamham jídlo
    jinak
      tvař se hladově
dosyta:
  najezse
  tvař se sytě

Cyklus můžeme také „zacyklit“ úplně, tedy udělat z něho nekonečný cyklus tím, že mu předepíšeme podmínku, která nepřestává být splněna. Můžeme například testovat nepřítomnost nějakého nesmyslu (dokud nevidíš škrblumpf), můžeme testovat světlo, když se pohybujeme ve stále osvětlených prostorách (dokud je světlo), nebo můžeme testovat přítomnost samotné opičky:[3]

  dokud vidíš opičku
    sever
    východ
    jih
    západ

Takovýto program by nechal opičku běhat pořád dokolečka (nebo přesněji dočtverečku) a kdybychom jím nechtěli opičku zahubit, museli bychom jej po čase přerušit sami zvenčí příkazem konec. Kdybychom ovšem tento příkaz využili uvnitř programu při splnění určité podmínky, dali bychom tím nekonečnému cyklu velmi praktický smysl:

  dokud vidíš opičku
    pokud nevidíš okno
      pokud nevidíš dveře
        konec
      potom
    potom
    uteč

Tento program nechává opičku znovu a znovu utíkat náhodným směrem (příkaz uteč si na sobě ostatně může vyzkoušet i hráč, viz pomoc uteč), ovšem toto utíkání se zastaví, když se opička ocitne v místnosti bez oken a bez dveří. Pokud Vám takový program ještě nepřijde dost praktický, představte si, že opička místo místnosti bez oken a bez dveří hledá třeba zdroj vody, potravu nebo určitého hráče. (Pokud nám při takovém náhodném hledání náhoda nepřeje, můžeme opičku kdykoli zastavit tím, že jí zahřímáme konec.)

Cykly jako spouštěče akcí

editovat

Připomeňme si první příklad z této lekce, jímž jsme nechali opičku čekat u Josefa a tím, jak se tváří, nabádat kolemjdoucí hráče k tomu, aby si řekli o sušenku. Představme si nyní, že z tohoto programu vyřadíme příkaz tvař se, tedy vyprázdníme tělo cyklu:

  dokud nevidíš sušenku
  potom
  vem sušenku
  jez sušenku

Cyklus na řádku 1 neobsahuje žádné příkazy, a tak se nedá zvenčí nijak poznat, že probíhá. Po spuštění takového programu bude tedy opička tiše stát u Josefa a nedělat nic, ale ve chvíli, kdy se na stole objeví sušenky, si jednu vezme a pustí se do ní. Cyklus, který „nedělá nic“, totiž přece jen něco dělá — v taktu provádění příkazů, tedy přibližně jednou za dvě sekundy, znovu a znovu testuje podmínku. Jakmile podmínka přestane platit, cyklus skončí a opička provede příkazy, které následují po něm.

Dokud jsme neuměli používat cykly, mohli jsme opičku pohnout do akce jedině přímým vyslovením příkazu. Pomocí prázdného cyklu hlídajícího splnění určité podmínky můžeme opičku nechat automaticky reagovat na určitou změnu situace, tedy třeba objevení nebo zmizení nějakého předmětu, příchod nebo odchod nějakého hráče, setmění nebo rozednění, opiččino vyhládnutí atd.:

  dokud nevidíš Šneka
  potom
  prohlédni si Šneka
  vyplázni jazyk na Šneka

Co všechno se dá takto pomocí prázdného cyklu spustit (a jak se to dá případně využít v rámci rozsáhlejších programů), to budiž přenecháno fantazii a experimentům laskavého čtenáře.

  • Naprogramujte příkaz, kterým se opička pustí do nějaké potravy, jejíž snědení trvá delší dobu (může to být třeba i sušenka, jaká se najde u Josefa), a po jejím dojedení si hlasitě říhne.
  • Naprogramujte příkaz, jímž opička jednotlivě přenosí všechny předměty určitého typu vyskytující se v jedné místnosti o jednu či několik místností dále a tam je nahromadí (například jednotlivě odnosí všechny sušenky, které jsou na stole u Josefa, do ledničky v kuchyni, nebo otrhá všechny plody z ostružiníku a udělá z nich hromádku ve vedlejší místnosti).
  • Naprogramujte opičku tak, aby nečinně čekala v místnosti, ale jakmile se v místnosti objeví určitý předmět (třeba sekera, o které jste se rozhodli, že se jí opička bojí), tak si opička tento předmět prohlédne, načež začne zmateně pobíhat, než najde místnost, kde se takový předmět nenachází.

Pracovní odkazy

editovat

Poznámky

editovat
  1. Nová verze Josefa, spuštěná v květnu 2023, doplňuje sušenku i v případě, že někdo v jeho přítomnosti vyjádří sušenku i beze slov, tedy se například tváří jako čekající na sušenku. Opička si tedy může nyní vyžádat sušenku i zatvářením a nemusí čekat na nikoho, kdo umí mluvit. Příklad s cyklem však samozřejmě funguje i nadále.
  2. Opička tady porušuje pravidla českého pravopisu, ale jinak to bohužel nejde. Podle pravopisných pravidel by se měla před slovo „až“ napsat čárka, ale čárka by znamenala konec příkazu a začátek příkazu dalšího, a proto ji zde musíme vynechat. Stávající verze opičky (listopad 2020) neobsahuje žádnou možnost, jak zadat čárku uprostřed příkazu.
  3. Stejně jako hráč, může si i opička prohlížet sebe samu, tedy se vidí a je dostatečně „chytrá“ na to, aby to dokázala rozpoznat.