Rekursive Prozeduren 1
Aus ProgrammingWiki
Wiki-Quelltext dieser Seite.
<language>Scheme</language>
==Turtle-Prozeduren==
[[Programmierparadigmen_-_Computerübungen|zur Übungsübersicht]]
Eine Turtle ist eine Zeichenroboter, den man sich wie eine Schildkröte mit Stift am Bauch vorstellen
kann. Sie lebt auf genau einer Zeichenfläche (<tt>canvas</tt>).
In den folgenden Beispielen werden Sie auf verschiedenen Zeichenflächen mit verschiedenen
Turtles arbeiten. Um diese anzusprechen, hat jede Fläche und jede Turtle einen eigenen Namen,
der man die Turtle identifiziert.
In der Regel wird die erste Zeichenfläche <tt>canvas1</tt> mit <tt>turtle1</tt>, <tt>canvas2</tt> mit <tt>turtle2</tt> und so weiter bearbeitet.
Sämtliche Kommandos, die eine Turtle versteht, finden sich in der folgenden Liste. <br/>
Das Aufrufmuster ist: ([comando] [turtle] [parameter])
===Befehlsliste===
{| border='1px'
|+ Turtle Befehle
! Befehl !! Beschreibung
|-
| home
| setzt die Turtle auf die Mitte der Zeichenfläche
|-
| move turtle x y
| setzt die Turtle auf den Punkt (x,y) der Zeichenfläche (Koordinatenursprung: linke obere Ecke)
|-
| forward turtle x
| lässt die Turtle x Schritte nach vorn gehen
|-
| backward turtle x
| lässt die Turtle x Schritte nach hinten gehen
|-
| pendown turtle
| setzt den stift ab, sodass Turtle-Bewegungen eine Spur hinterlassen (Standard)
|-
| penup turtle
| nimmt den stift hoch, sodass Turtle-Bewegungen keine Spur hinterlassen
|-
| penwidth turtle x
| Setzt die Stärke des Stiftes auf x
|-
| pencolor turtle r g b
| setzt die Farbe des Stiftes (Rot-Gelb-Grün-Werte im Bereich 0-255)
|-
| right turtle x
| dreht die Turtle um x Grad nach rechts
|-
| left turtle x
| dreht die Turtle um x Grad nach links
|-
| hide turtle
| blendet die Turtle aus
|-
| show turtle
| blendet die Turtle ein
|-
| clone turtle
| clont die Turtle in der Aktuellen Position
|-
| panerase turtle
| Die Turtle löscht die Markierungen, denen sie begegnet (wie ein Radiergummi).
|-
| clear canvas
| löscht die Zeichenfläche
|-
|}
===Beispiel===
Setzen Sie sich mit dem folgenden Beispiel auseinander und modifizieren Sie die Prozedur <tt>quad</tt>.
{|width="100%"
|-valign="top"
|width=600|<canvas width=600 height=300></canvas>||<code id="4ae30126a36cb">
(define quad
(lambda (turtle s)
(begin
(penwidth turtle 10)
(pencolor turtle 255 0 0)
(forward turtle s)
(right turtle 90)
(forward turtle s)
(right turtle 90)
(forward turtle s)
(right turtle 90)
(forward turtle s)
(right turtle 90))))
</code>
<eval id="4ae30126a3ec6">
(clear canvas1)
(home turtle1)
(quad turtle1 50)</eval>
|}
===Rechteck===
1. Schreiben Sie eine Prozedur, die ein Rechteck mit den Seitenlängen <tt>a</tt> und <tt>b</tt> mit
einer der <tt>turtle2</tt> auf <tt>canvas2</tt> zeichnet.
{|width="100%"
|-valign="top"
|width=600|<canvas width=600 height=300></canvas>||
<code id="4ae302a9cba62">
(define rechteck
(lambda (a b)
(forward turtle2 a)
(right turtle2 90)
(forward turtle2 b)
(right turtle2 90)
(forward turtle2 a)
(right turtle2 90)
(forward turtle2 b)
(right turtle2 90)))
</code>
<eval id="4ae302a9cc2f8">
(clear canvas2)
(move turtle2 20 180)
(rechteck 100 70)
</eval>
|}
===Nikolaus===
Schreiben Sie eine Prozedur, deren Ausführung <tt>turtle3</tt> auf <tt>canvas3</tt> das Haus vom
Nikolaus zeichnen lässt. Diese Prozedur soll als Argumente die entsprechende Turtle sowie die Länge der
Grundseite des Hauses verwenden.
{|width="100%"
|-valign="top"
|width=600|<canvas width=600 height=300></canvas>||
<code id="4ae304e7305a1">
(define nikolaus
(lambda (t s)
(forward t s)
(right t 45)
(forward t (/ s (sqrt 2)))
(right t 90)
(forward t (/ s (sqrt 2)))
(right t 135)
(forward t s)
(right t 225)
(forward t (* (sqrt 2) s))
(left t 135)
(forward t s)
(left t 135)
(forward t (* (sqrt 2) s))
(left t 135)
(forward t s)
(left t 90)))
</code>
<eval id="4ae304e730d68">
(clear canvas3)
(move turtle3 100 270)
(show turtle3)
(nikolaus turtle3 100)
</eval>
|}
===Turtle-Kreis===
Schreiben Sie eine rekursive Prozedur <tt>kreis</tt>, die die Turtle <tt>turtle4</tt> einen Kreis auf
<tt>canvas4</tt> zeichnen lässt. Überlegen Sie, welche Eingaben die Prozedur <tt>kreis</tt> nimmt: Ein
Turtle-Kreis ist ein 360-Eck. Jeder der 360 Turtle-Schritte beträgt 1 Längeneinheit (LE). Nach jedem
Schritt dreht sich die Turtle um 1 Grad nach rechts (oder links). Der Umfang dieses Kreises beträgt
offenbar 360 LE.
{|width="100%"
|-valign="top"
|width=600|<canvas width=600 height=300></canvas>||
<code id="4ae3069cd02b4">
(define kreis
(lambda (t winkel)
(if (> winkel 360)
'schluss
(begin
(forward t 2)
(right t 1)
(kreis t (+ winkel 1))))))
</code>
<eval id="4ae319c7a59ac">
(clear canvas4)
(move turtle4 200 150)
(kreis turtle4 0)</eval>
|}
===Turtle-Baum===
Erproben Sie die folgende rekursive Prozedur <tt>tree</tt> und machen Sie sich klar, wie die rekursive
Struktur des Baumes in der Prozedur direkt abgebildet wird.
{|width="100%"
|-valign="top"
|width=420|<canvas width=400 height=300></canvas>||
<code id="4ae31dd672c80">
;tree canvas5 turtle5
(define tree
(lambda(side turtle)
(cond
((< side 5) #t)
(else
(penwidth turtle (+ (/ side 10) 1 ))
(forward turtle side)
(left turtle 45)
(tree (/ side 2) turtle)
(right turtle 90)
(tree (/ side 2) turtle)
(left turtle 45)
(backward turtle side)))))
</code>
<eval id="4ae2fcc599117">
(clear canvas5)
(move turtle5 200 230)
(tree 100 turtle5)
</eval>
|}
===Random Walk===
<code id="4ae2fcc596a07" hidden>
(define random-maker
(let* ((multiplier 48271)
(modulus 2147483647)
(apply-congruence
(lambda (current-seed)
(let ((candidate (modulo (* current-seed multiplier)
modulus)))
(if (zero? candidate)
modulus
candidate))))
(coerce
(lambda (proposed-seed)
(if (integer? proposed-seed)
(- modulus (modulo proposed-seed modulus))
19860617)))) ;; an arbitrarily chosen birthday
(lambda (initial-seed)
(let ((seed (coerce initial-seed)))
(lambda args
(cond ((null? args)
(set! seed (apply-congruence seed))
(/ (- modulus seed) modulus))
((null? (cdr args))
(let* ((proposed-top
(ceiling (abs (car args))))
(exact-top
(if (inexact? proposed-top)
(inexact->exact proposed-top)
proposed-top))
(top
(if (zero? exact-top)
1
exact-top)))
(set! seed (apply-congruence seed))
(inexact->exact (floor (* top (/ seed modulus))))))
((eq? (cadr args) 'reset)
(set! seed (coerce (car args))))
(else
(display "random: unrecognized message")
(newline))))))))
</code>
Erarbeiten Sie eine rekursive Prozedur <tt>randomwalk</tt>, die eine Turtle und eine Schrittanzahl
erwartet und die Turtle bei jedem Schritt zufällig 0 bis 360 Grad nach rechts dreht und 0 bis 10 Pixel
vorwärts bewegt. Nach n Turtleschritten soll sich die Turtle genau auf dem eingeschlagenen Weg zum
Ausgangspunkt zurück bewegen und dabei die hinterlassene Spur löschen. Dabei ist es nicht gestattet,
den Weg explizit (z.B. in einer Liste) zu speichern.
Erstellen Sie vorher einen Zufallszahlengenerator, indem Sie für <init> eine beliebige wenigstens 10-
stellige natürliche Zahl verwenden.
<eval id="4ae324e93d0a4">(define random (random-maker <init>))</eval>
Danach bekommt man mit <tt>(random <zahl>)</tt> eine neue Zufallszahl zwischen <tt>0</tt> und
<tt>zahl</tt>.
<eval id="4ae324e93d852">(random <zahl>)</eval>
<code id="4ae49f4c05c63" hidden>
(define canvas6 (java-new <canvas> (->jint 6)))
(define turtle6 (java-new <turtle> (->jint 6)))
</code>
{|width="100%"
|-valign="top"
|width=420|<canvas width=400 height=300></canvas>||
<code id="4ae31dd6735b3">
(define randomwalk
(lambda (t weg winkel anzahl)
(if (= anzahl 0)
'Schluss
(begin
(forward t weg)
(right t winkel)
(randomwalk
t (random 60)(random 361)(- anzahl 1))
(penerase t)
(left t winkel)
(backward t weg)))))
</code>
<eval id="4ae2fcc5998f1">
;randomwalk canvas6 turtle6
(clear canvas6)
(randomwalk turtle6 10 34 60)
</eval>
|}
===Rosette===
{| width="80%"
|-valign="top"
|width=500|Lassen Sie sich von dieser schönen Rosette inspirieren und entwerfen Sie eine ähnliche.
Beginnen Sie mit der verbalen Beschreibung der zu zeichnenden Figur. Diese schreiben Sie dann in Form
einer rekursiven Turtle-Prozedur.||[[Bild:Rosette.jpeg|thumb|Rosette|50px]]
|}
<code id="4ae49f4c06452" hidden>
(define canvas7 (java-new <canvas> (->jint 7)))
(define turtle7 (java-new <turtle> (->jint 7)))
</code>
{| width="100%"
|-valign="top"
|width=500|<canvas width=480 height=300></canvas>||
<code id="4ae323cf4c73f">
(define rosette
(lambda (turtle seite delta winkel anzahl)
(cond
((> winkel 360) anzahl)
(else
(quad turtle seite)
(right turtle delta)
(rosette
turtle
seite
delta
(+ winkel delta)
(+ anzahl 1))))))
</code>
<eval id="4ae2fcc59a0e0">
(clear canvas7)
(move turtle7 240 150)
(rosette turtle7 70 20 0 0)
</eval>
|}
[[Programmierparadigmen_-_Computerübungen|zur Übungsübersicht]]