nepriama rekurzia

Príklad 4

Napíšte rekurzívny podprogram, ktorý nakreslí obrázok podľa zadaného stupňa (ak sa zadá 1 tak sa nakreslia len 4 štvorce, ak 2 tak sa nakreslí 4 štvorce a v kažnom z nich 4 kruhy, ak 3 tak sa nakreslí obrázok ako pri zadaní 2 a v každom kruhu budú 4 štvorce, atď.).

obrázok   obrázok  obrázok

Riešenie:

  1. Najprv si potrebujeme určiť, z akých rôznych časti sa skladá obrázok. Zo zadaných obrázkov vidíme, že jeden tvar sa opakuje 4 krát. Aby sme urobili čo najmenej krokov pri vykresľovaní štvorcov, budeme štvorce vykresľovať tak, že budú mať spoločný jeden bod.

    Procedúra pre štvorce vyzerá takto:
    viem stvorec
      opakuj 4
      [ opakuj 4
        [ pd
          do
          vl 90
        ]
        vl 90
      ]

    koniec


    Procedúra pre kruh bude vyzerať takto

    viem kruh
      elipsa[... ...]
    koniec

  2. K obom procedúram potrebujeme doplniť parametre, jeden parameter bude predstavovať veľkosť najväčšieho štvorca a druhý stupeň vykreslenia (koľko krát sa majú vykresliť štvorec a kruhy).
    Upravene procedúry budú vyzerať takto:

    viem stvorec :a :n
      opakuj 4
      [ opakuj 4
        [ pd
          do :a
          vl 90
        ]
        vl 90
      ]

    koniec

    viem kruh :a :n
      elipsa[:a/2 :a/2]
    koniec

  3. Teraz potrebujeme doplniť rekurzívne volanie. V procedúre štvorec je to ľahké. Z obrázka a podľa spôsobu vykreslenia sa kruh bude vykresľovať vždy po nakreslení jednej strany štvorca (z vnútornej strany). Teda nakreslí sa strana štvorca a potom sa zavolá procedúra kruh aby ona nakreslila kruh na koniec strany.
    Upravená procedúra štvorec:
    viem stvorec :a :n
      opakuj 4
      [ opakuj 4
        [ pd
          do :a
          kruh4 :a :n-1
          vl 90
        ]
        vl 90
      ]

    koniec


    Kruh sa vykresľuje zo stredu, takže do procedúry kruh musíme doplniť príkazy presunu. Po dokreslení čiary sme natočení v smere vykresľovania. Potrebujeme sa otočiť a dostať sa po diagonále štvorca na miesto, kde je stred kruhu (ako ďaleko musíme ísť z rohu štvorca so stredu kruhu si vypočítame pomocou Pytagorovej vety). Ako sa dostaneme k vykresleniu kruhu, tak sa po jeho vykreslení musíme dostať naspäť, aby sa mohla nakresliť ďalšia čiara.
    Upravená procedúra kruh:
    viem kruh :a :n
      vl 135
      ph
      do (:a/sqrt(2))/2
      pd
      elipsa[:a/2 :a/2]
      ph
      vz (:a/sqrt(2))/2
      vp 135
    koniec

    Potrebujeme ešte doplniť rekurzívne volanie v procedúre kruh. Vieme, že štvorce sa vykresľujú zo stredu, ten istý bod je aj stred kruhu, teda sa nemusíme premiestňovať, stačí sa nám otočiť do správneho smeru. V tomto smere akom sme natočení, by sa vykreslil štvorec šikmo. Teda otočíme sa o 45° doľava. Pri tomto otočení úž môžeme zavolať procedúru štvorce. Tu musíme dopočítať opäť veľkosť strany štvorca (lebo polomer kruhu je uhlopriečna štvorca).
    Upravená procedúra kruh vyzerá takto:

    viem kruh :a :n
      vl 135
      ph
      do (:a/sqrt(2))/2
      pd
      elipsa[:a/2 :a/2]
      vl 45
      stvorec4 (:a*sqrt(2))/8 :n-1
      vp 45
      ph
      vz (:a/sqrt(2))/2
      vp 135
    koniec

  4. Takto upravené procedúry budú kresliť čo chceme, ale nikdy sa to neskončí. Takže musíme doplniť podmienku ukončenia. Vieme, že parameter n udáva stupeň vykreslenia aj to, že každým rekurzívnym volaním sa tento parameter znižuje. Teda podmienka ukončenia bude ak n<0. Inak povedané podmienka vykonávania procedúry bude pokiaľ n>0 .
    Celkom upravené procedúry sú:

    viem kruh :a :n
      ak :>0
      [ vl 135
        ph
        do (:a/sqrt(2))/2
        pd
        elipsa[:a/2 :a/2]
        vl 45
        stvorec4 (:a*sqrt(2))/8 :n-1
        vp 45
        ph
        vz (:a/sqrt(2))/2
        vp 135
      ]  
    koniec

    viem stvorec :a :n
      ak :n>0
      [ opakuj 4
        [ opakuj 4
          [ pd
            do :a
            kruh4 :a :n-1
            vl 90
          ]
          vl 90
        ]
      ]  

    koniec

    Aby sme nakreslili požadovaný útvar tak sa zavolá napríklad procedúra KRUH 2

Ak nie je vidieť Imagine projekt, treba stiahnuť Imagine plugin