On this page:
8.1 Tutorial
8.1.1 Verbesserungen
8.2 Prozeduren
turtle
set-color
turn
draw
move
run
sequence

8 Turtle-Grafik: "turtle.ss"

Note: This is documentation for the "turtle.rkt" teachpack that goes with the German textbook Die Macht der Abstraktion.

Turtle-Grafik ist eine Methode zum Erstellen von Computergrafiken. Das Zeichnen wird dabei durch das Bewegen einer virtuellen Schildkröte über den Zeichenbereich modelliert. Eine Schildkröte kann durch drei Befehle bewegt werden:

Wir stellen jetzt ein Teachpack für DrRacket vor, mit dessen Hilfe solche Turtle-Grafiken erstellt werden können.

8.1 Tutorial

Unser Ziel ist es, in diesem Tutorial ein Quadrat mithilfe der Prozeduren des Teachpacks zu zeichnen. Aus diesem Grund müssen wir zunächst mit der Prozedur draw eine Linie nach rechts malen. Die initiale Ausgansposition der Turtle ist in der Bildmitte mit Blick nach rechts. Mit (draw 20) bewegen wir die Turtle dann 20 Pixel nach rechts und zeichnen dabei. Um das resultierende Bild zu sehen ist, müssen wir die Turtle mittels der Prozedur run laufen lassen. Die restlichen Parameter für run sind die Höhe und die Breite des Bildes sowie die Farbe, in der gezeichnet werden soll. Geben Sie also folgenden Befehl in die REPL ein, um Ihre erste Turtle-Grafik zu erstellen:

(run (draw 20) 100 100 "red")

Sie erhalten dann eine Ausgabe wie die folgende:

Nun vervollständigen wir die Linie zu einem rechten Winkel: wir drehen die Turtle um 90° nach rechts und zeichnen dann eine Line der Länge 20 Pixel nach unten. Zum Drehen einer Turtle verwenden wir die Prozedur turn.

Da wir ein Quadrat aus zwei rechten Winkeln zusammensetzen können, abstrahieren wir über das Zeichnen des rechten Winkels. Dazu schreiben wir eine Prozedur right-angle die als Parameter eine Turtle erhält:

(: right-angle (turtle -> turtle))
(define right-angle
  (lambda (t1)
    (let* ((t2 ((draw 20) t1))
           (t3 ((turn -90) t2))
           (t4 ((draw 20) t3)))
      t4)))

Das Ergebnis sieht dann so aus:

Um das Quadrat komplett zu zeichnen, sollen nun zwei rechte Winkel verwendet werden. Wir zeichnen also einen rechten Winkel, drehen uns um 90° nach rechts, und zeichnen einen zweiten rechten Winkel.

(: square (turtle -> turtle))
(define square
  (lambda (t1)
    (let* ((t2 (right-angle t1))
           (t3 ((turn -90) t2))
           (t4 (right-angle t3)))
      t4)))

So sieht das Ergebnis aus:

8.1.1 Verbesserungen

An dem Beispiel ist leicht zu sehen, dass es zum Zeichnen mit Hilfe von Turtle-Grafik oft erforderlich ist, Zwischenwerte wie t1, t2 etc., an die nächste Prozedur weiterzureichen, die Werte ansonsten aber nicht weiterverwendet werden. Beispielsweise werden in der obigen Definition von square die Variablen t1, ..., t4 nur gebraucht, um die Prozeduren right-angle, (turn -90) und right-angle hintereinander auszuführen.

Um solche Fälle einfach programmieren zu können, enthält das Turtle-Teachpack die Prozedur sequence. Damit können wir eine zu right-angle äquivalente Version wesentlicher einfacher aufschreiben:

(define right-angle2
  (sequence (draw 20) (turn -90) (draw 20)))

Ebenso wie right-angle können wir square leichter schreiben als:

(define square2
  (sequence right-angle (turn -90) right-angle))

8.2 Prozeduren

value

turtle : signature

Dies ist die Signatur für Turtles.

value

set-color : (color -> (turtle -> turtle))

Diese Prozedur ist eine Prozedurfabrik. Sie liefert als Ergebnis eine Prozedur, die auf eine Turtle anwendbar ist. Wendet man das Ergebnis auf eine Turtle an, so ändert dies die Farbe mit der gezeichnet wird.

Folgender Code

(define square3
  (sequence right-angle (turn -90) (set-color "blue") right-angle))
liefert dieses Bild:

value

turn : (number -> (turtle -> turtle))

Diese Prozedur ist eine Prozedurfabrik. Sie liefert als Ergebnis eine Prozedur, die auf eine Turtle anwendbar ist. Wendet man das Ergebnis auf eine Turtle an, so ändert sich die Blickrichtung der Turtle um die gegebene Gradzahl gegen den Uhrzeigersinn.

value

draw : (number -> (turtle -> turtle))

Diese Prozedur ist eine Prozedurfabrik. Sie liefert als Ergebnis eine Prozedur, die auf eine Turtle anwendbar ist. Wendet man das Ergebnis auf eine Turtle an, so bewegt sich die Schildkröte um die gegebene Anzahl von Pixel und zeichnet dabei eine Linie.

value

move : (number -> (turtle -> turtle))

Diese Prozedur ist eine Prozedurfabrik. Sie liefert als Ergebnis eine Prozedur, die auf ein Turtle anwendbar ist. Wendet man das Ergebnis auf eine Turtle an, so bewegt sich die Schildkröte um die gegebene Anzahl von Pixel, zeichnet dabei aber keine Linie.

value

run : ((turtle -> turtle) number number color -> image)

Diese Prozedur wendet die übergebene Prozedur von Turtle nach Turtle auf die initiale Schildkröte an und zeigt das daraus resultierende Bild an. Der zweite Parameter ist die Höhe des Bilds, der dritte Parameter die Breite des Bilds und der vierte Parameter die Farbe, mit der gezeichnet wird.

value

sequence : ((turtle -> turtle) ... -> (turtle -> turtle))

Diese Prozedur nimmt eine beliebige Anzahl von Turtle-Veränderungen (d.h. Prozeduren mit Signatur turtle -> turtle) und erstellt eine neue Prozedur, die die Veränderungen der Reihe nach von links nach rechts abarbeitet.