Scheme Turtle

Aus ProgrammingWiki

Wiki-Quelltext dieser Seite.

<language>Scheme</language>

==Turtle Geometrie==

Die Turtle Geometrie ist aus der Programmiersprache LOGO sehr gut bekannt. Es handelt sich um eine koordinatenfreie Geometrie. Die Idee besteht darin, einen kleinen Zeichenroboter, dargestellt als Schildkröte (Turtle genannt), mit bestimmten Befehlen zu steuern. Da die Turtle am Bauch einen Stift besitzt, kann sie bei ihren Bewegungen eine Spur hinterlassen. Das Schildkrötensymbol lässt die jeweils aktuelle Blickrichtung der Turtle erkennen. Die Vorwärts/Rückwärts-Bewegungen finden in dieser Blickrichtung statt. Diese kann durch Rechts/Links-Drehungen verändert werden.

===Zeichenfläche===

Als erstes benötigen wir eine "Spielwiese", auf der sich unsere Turtle tummeln kann. Das folgende Rechteck zeigt dieses Areal, das auch als Zeichenfläche (Canvas, auch Leinwand) bezeichnet wird. 

<canvas></canvas>

Wenn man nicht die Standardgröße verwendet, kann man mit den Attributen <tt>width</tt> und <tt>height</tt> die Breite und Länge explizit festlegen. In unserem Beispiel wurde 

 <nowiki><canvas width=300 height=200></canvas></nowiki>

verwendet. Wir arbeiten jetzt mit dieser Standardgröße weiter.

Auf diese Zeichenfläche setzen wir nun eine Turtle.
<eval>
(clear canvas)
(home turtle)
</eval>

Der Befehl ''home'' setzt die Turtle etwa in die Mitte der Zeichenfläche. Wenn uns die aktuelle Turtle-Position nicht gefällt, bewegen wir die Turtle auf einen anderen Platz.

===Turtle-Bewegungen===
<code hidden>(home turtle)</code>
<eval>
(forward turtle 50)
</eval>

lässt die Turtle 50 Schritte vorwärts laufen. Analog gilt dies auch für ''backward'' (rückwärts). Soll keine Spur gezeichnet werden, kann die Turtle den Stift anheben (und später wieder absenken).

<code hidden>(home turtle)</code>
<eval>
(forward turtle 20)
(penup turtle)
(forward turtle 20)
(pendown turtle)
(forward turtle 20)
</eval>

Da die Zeichenfläche nun den sichtbaren Bereich dieser Seite verlässt, brauchen wir entweder eine neue Wiki-Seite oder auf dieser hier eine neue canvas. Wir nehmen hier den zweiten Weg. 

<canvas></canvas>

Im Evaluationsfenster müssen wir allerdings beachten, dass wir nun <tt>canvas2</tt> ansprechen. Auf canvas2 sitzt turtle2. Allgemein sitzt auf canvas_n turtle_n, wobei n=2,3,4,5. Der Standardfall ist n=1, ohne die 1 zu schreiben.

In folgendem Beispiel kommen Drehbewegungen (um einen bestimmten Winkel) und Vorgaben für Linienstärken und deren Farbe hinzu.

<eval>
(clear canvas2)
(home turtle2)
(penwidth turtle2 5)
(pencolor turtle2 255 0 0)
(forward turtle2 50)
(right turtle2 90)
(pencolor turtle2 255 255 0)
(forward turtle2 50)
(right turtle2 90)
(pencolor turtle2 0 0 255)
(forward turtle2 50)
</eval>




(define t (clone turtle)) 
(hide t)
(forward t 50)
(right t 90)
(forward t 50)
(show t)
(setangleto t turtle)


<eval>
(clear canvas2)
(move turtle2 200 200)

(define tree
 (lambda(side winkel) 
  (cond [(< side 4) #t] 
        [else  
          (penwidth turtle2 (+ (/ side 10) 1 ))    
          (forward turtle2 side)  
          (left turtle2 winkel)  
          (tree (/ side 2) winkel)  
          (left turtle2 winkel)  
          (tree (/ side 2) winkel)  
          (right turtle2 (* 4 winkel))  
          (tree (/ side 2) winkel)  
          (left turtle2 winkel)  
          (tree (/ side 2) winkel)  
          (left turtle2 winkel)  
          (backward turtle2 side)])))

(tree 100 25)
</eval>

<canvas></canvas>

Die folgende Prozedure <tt>tree</tt> verwendet einen Parameter für die ''turtle''.

<eval>
(clear canvas3)
(move turtle3 200 200)

(define tree
 (lambda(side turtle) 
  (cond 
    ((< side 2) #t)
    (else  
      (penwidth turtle (+ (/ side 10) 1 ))    
      (forward turtle side)  
      (left turtle 45)  
      (tree (/ side 2) (clone turtle))  
      (right turtle 90)  
      (tree (/ side 2) (clone turtle))  
      (left turtle 45)  
      (backward turtle side)))))

(tree 100 turtle3)
</eval>
<canvas></canvas>

Zur Erforschung echter Rekursion verwenden wir die Prozedur <tt>random-walk</tt>. 

<code 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>
<eval>
(define random
  (random-maker 19768116))  ;; Anfangswert verändern!

(clear canvas4)
(move turtle4 200 310)
(pencolor turtle4 0 0 200)

(define random-walk
  (lambda (angle length n turtle)
    (if (= n 0)
        ;(penerase turtle)
        (pencolor turtle4 220 0 0)
        (begin          
          (forward turtle length)
          (right turtle angle)
          (random-walk (+ 5 (random angle))(+ 5 (random length)) (- n 1) turtle)
          ;(sleep-for-a-while 0.01)
          (left turtle angle)
          (backward turtle length)))))

(random-walk 360 20 1000 turtle4)
</eval>
<canvas h=500></canvas>