<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xml" href="/cjs/screen.xsl" media="screen"?>
<lecture>

<meta>
  <maintitle>Karel</maintitle>
  <author>Jiří Znamenáček</author>
  <title>Průchod bludištěm</title>
  <date>2026-10-01</date>
  <link><!--a href="http://vyuka.ookami.cz" rel="external">http://vyuka.ookami.cz</a--></link>
</meta>
<!--
  „“–
  ↵ aneb &#x21B5; aneb \r aneb CR aneb CarriageReturn
-->


<slide title="Úvod">

    <p>
        Ač to tak možná na první pohled nevypadá, Karla je možné velmi snadno naučit procházet bludištěm. Asi každý jste totiž někdy slyšeli o tzv. <em>pravidlu pravé ruky</em> (případně též i <em>levé</em>) – držte se pravou rukou zdi a z bludiště nakonec někdy vyjdete<sup>*</sup>. Pravda, občas si při tom pěkně zajdete, ale jinak to funguje celkem pěkně.
    </p>
    <img src="_files/maze/mesto_1.jpg" width="481" height="502" alt="Bludiště bez ukončovací značky" />
    <notes>
        <note>
            Zdrojový kód města: <a href="_files/maze/prava_ruka_mesto.k">prava_ruka_mesto.k</a>
        </note>
        <note>
            <sup>*</sup> Až na jeden zváštní typ bludišť–nebludišť, kde toto pravidlo beznadějně selže. <a href="?slajd=">Na taková se musí jinak.</a>
        </note>
        <note>
            Původní kód pro průchod bludištěm podle publikace: <cite>Vejvoda, Michal; Rytíř, Miroslav: „Programovací jazyk KAREL“. Český Krumlov, 1987-2001.</cite>
        </note>
    </notes>
    
</slide>
<slide title="Řešení rekurzí">

    <p>
        Přepsat uvedené pravidlo pomocí rekurze je velmi jednoduché:
    </p>
    <example lang="karel" src="_files/maze/prava_ruka_mod.k99" />
    <p>
        Prvních šest řádek kódu před vlastním rekurzivním voláním (po němž už se nic dalšího nevykonává!) nedělá nic jiného než:
    </p>
    <ol>
        <li>
            je-li před Karlem zeď, otočí se vlevo a zavolá tento test rekurzí znovu;
        </li>
        <li>
            není-li před Karlem zeď, může udělat krok, načež se otočí vpravo, aby v dalším rekurzivním kroku znovu otestovat, zda tam náhodou už není chodba (tedy není zeď).
        </li>
    </ol>
    <p>
        Karel se tedy poslušne posouvá vždy o jeden krok a pokaždé zkouší, zda je vedle něj ještě pořád zeď, nebo už může zatočit do další chodby.
    </p>

</slide>
<slide title="Označení cíle I">

    <p>
        Vidíme, že Karel – pochopitelně – nepozná, že z bludiště už vyšel, takže se bude <em>pravidla pravé ruky</em> úporně držet dál a zase se do něj vrátí. To by se dalo zařídit doplněním nějaké podmínky, kupříkladu přesunutím <code>DOMOV</code>a k východu (případně položením značky tamtéž):
    </p>
    <img src="_files/maze/mesto_2.jpg" width="481" height="502" alt="Bludiště s ukončovací značkou" />
    <note>
        Zdrojový kód města: <a href="_files/maze/bludiste_mesto.k">bludiste_mesto.k</a>
    </note>

</slide>
<slide title="Označení cíle II">

    <p>
        Program s doplněnou podmínkou pro zastavení v případě nalezení <code>DOMOV</code>a:
    </p>
    <example lang="karel" src="_files/maze/ruce_mod.k99" />
    <p>
        PS: Do programu jsem zároveň doplnil i variantu algoritmu <em>pravidlo levé ruky</em>, která zjevně funguje stejně, jen Karel prochází jinou cestou (v jistém smyslu doplňkovou k té první).
    </p>

</slide>
<slide title="Označení cíle III">
    
    <p>
        Jelikož Karel hledá cestu z bludiště podél zdi (ať už pravé nebo levé), je jasné, že ukončovací značka (v našich příkladech <code>DOMOV</code>) musí také ležet u zdi, jinak ji Karel mine.
    </p>
    <p>
        ...
    </p>
    
</slide>
<slide title="Úplné nahrazení rekurze smyčkou">
    
    <p>
        Nahradit <em>koncovou rekurzi</em> (tedy takovou, kde je rekurzivní volání na konci procedury a po něm už nenásleduje žádný další kód) smyčkou/cyklem je velmi jednoduché – stačí zaměnit podmínku řízení rekurze za cyklus řízený podmínkou:
    </p>
    <example lang="karel">
        PRAVÁ RUKA CYKLEM
          DOKUD NENÍ DOMOV
            KDYŽ JE ZEĎ
              VLEVO VBOK
            KONEC, JINAK
              KROK
              VPRAVO VBOK
            KONEC
          KONEC
        KONEC
    </example>
    <p>
        Pro toho, kdo nezná rekurzi, je to asi nejprůhlednější kód – dokud Karla nedojde do DOMOVa, neustále kráčí kolem zdi (na své pravé straně).
    </p>
    
</slide>
<slide title="PS: Ušetření několika rekurzivních kroků pomocí smyčky">

    <p>
        Z kódu je vidět, že kromě vlastní cesty ven z bludiště zařizuje rekurze především hledání volné cesty pro další krok. Téhož se dá dosáhnout za pomoci smyčky s podmínkou, čímž si v případě nevhodného natočení Karla vůči zdem můžeme ušetřit spoustu rekurzivních kroků:
    </p>
    <example lang="karel" src="_files/maze/bludiste_mod.k99" />
    <p>
        Jen si musíme dát pozor – kde jsme se u podmínky KDYŽ otočili vpravo po kroku vpřed, cyklus DOKUD nic takového nemá, takže se doprava musíme otočit dříve, než se začneme ptát, zda stojíme pravou rukou ke zdi. Jinak se se zlou potážeme a z bludiště se asi jen tak nedostaneme (schválně si to zkuste :-).
    </p>
    <p>
        PS: Vlastní hledání cesty ven z bludiště je stejné jako u předchozího řešení a zajišťuje ho rekruze. Ale porovnáním s předchozím kódem bez rekurze je otázka, jak moc je tahle úprava přehledná.
    </p>

</slide>
<!--
    <p>
        Jak už jsme varovali, ne z každého bludiště se dá <em>pravidlem pravé/levé ruky</em> bezpečně vyjít. V podstatě existují dva typy bludišť – jedny, které se dají rozkreslit do <strong>grafu</strong> v podobě tzv. <strong>stromu</strong>, a druhé, u nichž toto rozkreslení bude obsahovat <strong>cykly</strong> (neboli uzavřené smyčky).
    </p>

-->
<slide title="Grafy, stromy, cykly I">

    <p>
        Nakresleme si do každé křižovatky a na konec každé chodby puntík a spojme je po chodbách čarami:
    </p>
    <img src="_files/maze/mesto_2_s-grafem.jpg" width="481" height="502" alt="Bludiště bez cyklu s grafem" />

</slide>
<slide title="Grafy, stromy, cykly II">

    <p>
        Když si vezmeme pouze nakreslené, obdržíme strukturu, které se se říká <strong>graf</strong>:
    </p>
    <img src="_files/maze/mesto_2_graf.jpg" width="384" height="368" alt="Bludiště bez cyklu – graf" />
    <p>
        Puntíkům za konce chodeb (a cíl) a křižovatky se říká <strong>uzly</strong> a spojnicím uzlů <strong>hrany</strong>. Pokud cíl nazveme <strong>kořenem</strong> (a umístíme si ho otočením obrázku o 90 ° ve směru hodinových ručiček v duchu nahoru), dostaneme typ grafu, kterému se říká <strong>strom</strong>. Uzly na koncích jsou pak tzv. <strong>listy</strong>.
    </p>
    <p>
        Přitom je snadno vidět, že v takovémto grafu, ať Karel začne kdekoli, <em>pravidlem pravé/levé ruky</em> se vždy dostane do každého jiného uzlu, především pak tedy do cíle. A to právě proto, že <em>tento graf je stromem</em>.
    </p>

</slide>
<slide title="Grafy, stromy, cykly III">

    <p>
        Nicméně pokud naše bludiště bude vypadat třebas takto..
    </p>
    <img src="_files/maze/mesto_3.jpg" width="481" height="502" alt="Bludiště s cyklem (a ukončovací značkou)" />
    <note>
        Zdrojový kód města: <a href="_files/maze/bludiste_s_cyklem_mesto.k">bludiste_s_cyklem_mesto.k</a>
    </note>
    <p>
        ..máme problém :-)
    </p>

</slide>
<slide title="Grafy, stromy, cykly IV">

    <p>
        Takovýto <em>graf</em> totiž obsahuje <strong>cykly</strong> (zde tedy jenom jeden)..
    </p>
    <img src="_files/maze/mesto_3_s-grafem.jpg" width="481" height="502" alt="Bludiště s cyklem a grafem" />
    <p>
        ..a už to není <em>strom</em>.
    </p>

</slide>
<slide title="Grafy, stromy, cykly V">

    <p>
        Je to prostě nějaký obecný graf, ale především je to <em>graf s cyklem</em>:
    </p>
    <img src="_files/maze/mesto_3_graf.jpg" width="248" height="320" alt="Bludiště s cyklem – graf" />
    <p>
        A v grafu s cykly <em>pravidlo pravé/levé ruky</em> selže – Karel se bude neustále motat kolem stejné zdi a nikdy z bludiště nevyjde. Jak si můžete snadno vyzkoušet i prakticky, nejen v duchu.
    </p>

</slide>
<!--slide title="Řešení problému pro bludiště s cykly">

    <p>
        Ale i takovéto bludiště se dá projít. Stačí, aby si Karel značkoval chodby, kterými již prošel, a znovu se do nich nevracel (a zkusil tedy z příslušné křižovatky najít jinou, dosud nepoužitou, cestu).
    </p>
    <p>
        Nejlépe se značkuje položením značky (proto jsme také východ z bludiště označili jako <code>DOMOV</code>) a řešení je pak následující:
    </p>
    <example lang="karel">
    </example>

</slide-->


</lecture>
