Ein Baum besteht aus einem Stamm und zwei kleineren Bäumen, ein Farnblatt aus einem Stück Stiel und drei kleineren Farnblättern. Mit einer Funktion, die sich selbst aufruft, zeichnet die Schildkröte solche Bilder in wenigen Zeilen: Bäume, die schief wachsen oder bis zum Boden hängen, ein Farnblatt, das Sierpiński-Dreieck, die Koch-Kurve und die Hilbert-Kurve.
Die Befehle der Schildkröte kennst du aus Turtle: Bilder aus Befehlen, Funktionen, die sich selbst aufrufen, aus den Katas: Rekursion. Hier kommt beides zusammen: Jede Figur auf dieser Seite besteht aus kleineren Kopien ihrer selbst. Wie, zeigt vor jeder Aufgabe ein Bild, das du Stufe für Stufe durchklickst; was aus der Stufe davor stammt, ist farbig.
Ein Baum ist ein Stamm, an dem links und rechts ein kleinerer Baum wächst. Jeder davon ist wieder ein Stamm mit zwei kleineren Bäumen, und so weiter, bis die Bäume so klein sind, dass die Funktion aufhört. Klick dich durch die Stufen: Jede Stufe besteht aus einem Stamm und zwei Bäumen der Stufe davor, in Farbe.
Wer die Funktion schreibt, muss also nur zwei Fragen beantworten: Was zeichnet die kleinste Stufe? Und wie setzt sich eine Stufe aus der davor zusammen? Den Rest erledigen die Aufrufe von selbst.
Schreib tree(size, depth) für den Baum aus dem Bild oben: Bei der Tiefe 0 zeichnet sie nichts, sonst einen Stamm der Länge size mit zwei kleineren Bäumen daran. Danach steht die Schildkröte wieder unten am Stamm und schaut wie vorher.
Bei der Tiefe 0 kehrt die Funktion sofort zurück. Das ist das Ende der Rekursion: Ohne diese Zeile ruft sie sich für immer selbst auf.
Sonst: den Stamm vorwärts, 30 nach links, tree(size * 0.7, depth - 1) für den linken Baum, 60 nach rechts, derselbe Aufruf für den rechten, und 30 nach links zurück.
Am Ende den Stamm zurück: Erst dann steht die Schildkröte nach dem linken Baum wieder dort, wo der rechte anfängt.
Schreib tree(size, depth) für den Baum aus dem Bild oben: Bei der Tiefe 0 zeichnet sie nichts, sonst einen Stamm der Länge size mit zwei kleineren Bäumen daran. Danach steht die Schildkröte wieder unten am Stamm und schaut wie vorher.
Bei der Tiefe 0 kehrt die Funktion sofort zurück. Das ist das Ende der Rekursion: Ohne diese Zeile ruft sie sich für immer selbst auf.
Sonst: den Stamm vorwärts, 30 nach links, tree(size * 0.7, depth - 1) für den linken Baum, 60 nach rechts, derselbe Aufruf für den rechten, und 30 nach links zurück.
Am Ende den Stamm zurück: Erst dann steht die Schildkröte nach dem linken Baum wieder dort, wo der rechte anfängt.
Schreib tree(size, depth) für den Baum aus dem Bild oben: Bei der Tiefe 0 zeichnet sie nichts, sonst einen Stamm der Länge size mit zwei kleineren Bäumen daran. Danach steht die Schildkröte wieder unten am Stamm und schaut wie vorher.
Bei der Tiefe 0 kehrt die Funktion sofort zurück. Das ist das Ende der Rekursion: Ohne diese Zeile ruft sie sich für immer selbst auf.
Sonst: den Stamm vorwärts, 30 nach links, tree(size * 0.7, depth - 1) für den linken Baum, 60 nach rechts, derselbe Aufruf für den rechten, und 30 nach links zurück.
Am Ende den Stamm zurück: Erst dann steht die Schildkröte nach dem linken Baum wieder dort, wo der rechte anfängt.
Mach aus dem Baum von eben einen schönen: Jeder Ast ist so dick wie seine Tiefe (width depth), die Äste mit der Tiefe 1 und 2 sind grün ("forestgreen"), alle anderen braun ("saddlebrown"). Die Äste drehen sich um 25 Grad und sind 0,75-mal so lang wie der davor. Zurück geht die Schildkröte mit gehobenem Stift, sonst malt sie den braunen Ast in der Farbe des letzten Blatts nach.
Breite und Farbe setzt die Funktion am Anfang, bevor sie den Ast zeichnet: Dann gelten sie für ihn.
Die Farbe hängt von der Tiefe ab: color depth <= 2 ? "forestgreen" : "saddlebrown", oder mit if und else.
Am Ende: Stift hoch, den Ast zurück, Stift wieder runter.
Mach aus dem Baum von eben einen schönen: Jeder Ast ist so dick wie seine Tiefe (width(depth)), die Äste mit der Tiefe 1 und 2 sind grün ("forestgreen"), alle anderen braun ("saddlebrown"). Die Äste drehen sich um 25 Grad und sind 0,75-mal so lang wie der davor. Zurück geht die Schildkröte mit gehobenem Stift, sonst malt sie den braunen Ast in der Farbe des letzten Blatts nach.
Breite und Farbe setzt die Funktion am Anfang, bevor sie den Ast zeichnet: Dann gelten sie für ihn.
Die Farbe hängt von der Tiefe ab: if depth <= 2: grün, else: braun.
Am Ende: Stift hoch, den Ast zurück, Stift wieder runter.
Mach aus dem Baum von eben einen schönen: Jeder Ast ist so dick wie seine Tiefe (width(depth)), die Äste mit der Tiefe 1 und 2 sind grün ("forestgreen"), alle anderen braun ("saddlebrown"). Die Äste drehen sich um 25 Grad und sind 0,75-mal so lang wie der davor. Zurück geht die Schildkröte mit gehobenem Stift, sonst malt sie den braunen Ast in der Farbe des letzten Blatts nach.
Breite und Farbe setzt die Funktion am Anfang, bevor sie den Ast zeichnet: Dann gelten sie für ihn.
Die Farbe hängt von der Tiefe ab: color(depth <= 2 ? "forestgreen" : "saddlebrown"), oder mit if und else.
Am Ende: Stift hoch, den Ast zurück, Stift wieder runter.
Ein Baum, in dem links und rechts dasselbe passiert, sieht aus wie gezeichnet. Andere Winkel und andere Längen für jede Seite, und er wächst wie ein echter:
Echte Bäume wachsen nicht gleichmäßig. Ändere deinen schönen Baum: Der linke Ast dreht sich um 15 Grad und wird 0,8-mal so lang, der rechte dreht sich um 40 Grad und wird 0,6-mal so lang. Breite und Farben bleiben wie eben.
Der linke und der rechte Baum bekommen jetzt verschiedene Zahlen: size * 0.8 und size * 0.6.
Die Drehungen müssen zusammenpassen: 15 nach links für den linken Baum, dann 15 + 40 = 55 nach rechts für den rechten, und am Ende 40 nach links zurück.
Echte Bäume wachsen nicht gleichmäßig. Ändere deinen schönen Baum: Der linke Ast dreht sich um 15 Grad und wird 0,8-mal so lang, der rechte dreht sich um 40 Grad und wird 0,6-mal so lang. Breite und Farben bleiben wie eben.
Der linke und der rechte Baum bekommen jetzt verschiedene Zahlen: size * 0.8 und size * 0.6.
Die Drehungen müssen zusammenpassen: 15 nach links für den linken Baum, dann 15 + 40 = 55 nach rechts für den rechten, und am Ende 40 nach links zurück.
Echte Bäume wachsen nicht gleichmäßig. Ändere deinen schönen Baum: Der linke Ast dreht sich um 15 Grad und wird 0,8-mal so lang, der rechte dreht sich um 40 Grad und wird 0,6-mal so lang. Breite und Farben bleiben wie eben.
Der linke und der rechte Baum bekommen jetzt verschiedene Zahlen: size * 0.8 und size * 0.6.
Die Drehungen müssen zusammenpassen: 15 nach links für den linken Baum, dann 15 + 40 = 55 nach rechts für den rechten, und am Ende 40 nach links zurück.
Dreht sich jeder Ast weit genug und wird er nur wenig kürzer, biegen sich die äußeren Äste bis zum Boden. Ändere deinen schönen Baum: Beide Äste drehen sich um 36 Grad und werden 0,84-mal so lang; die Breite ist depth * 0.7, die Äste mit einer Tiefe bis 3 sind "olivedrab", die anderen "sienna". Er beginnt mit tree(52, 10).
Es ändern sich nur Zahlen und Farben: 36 statt 25 Grad, 0,84 statt 0,75, depth * 0.7 für die Breite.
Nach dem linken Baum dreht sich die Schildkröte 72 Grad nach rechts, für den rechten, und am Ende 36 Grad nach links zurück.
Dreht sich jeder Ast weit genug und wird er nur wenig kürzer, biegen sich die äußeren Äste bis zum Boden. Ändere deinen schönen Baum: Beide Äste drehen sich um 36 Grad und werden 0,84-mal so lang; die Breite ist depth * 0.7, die Äste mit einer Tiefe bis 3 sind "olivedrab", die anderen "sienna". Er beginnt mit tree(52, 10).
Es ändern sich nur Zahlen und Farben: 36 statt 25 Grad, 0,84 statt 0,75, depth * 0.7 für die Breite.
Nach dem linken Baum dreht sich die Schildkröte 72 Grad nach rechts, für den rechten, und am Ende 36 Grad nach links zurück.
Dreht sich jeder Ast weit genug und wird er nur wenig kürzer, biegen sich die äußeren Äste bis zum Boden. Ändere deinen schönen Baum: Beide Äste drehen sich um 36 Grad und werden 0,84-mal so lang; die Breite ist depth * 0.7, die Äste mit einer Tiefe bis 3 sind "olivedrab", die anderen "sienna". Er beginnt mit tree(52, 10).
Es ändern sich nur Zahlen und Farben: 36 statt 25 Grad, 0,84 statt 0,75, depth * 0.7 für die Breite.
Nach dem linken Baum dreht sich die Schildkröte 72 Grad nach rechts, für den rechten, und am Ende 36 Grad nach links zurück.
Ein Farnblatt wächst wie ein Baum, nur anders: Sein Stiel biegt sich bei jedem Schritt ein wenig, und an jedem Schritt wächst links und rechts ein kleines Farnblatt. Was nach diesem Schritt kommt, ist wieder ein Farnblatt, nur ein bisschen kleiner.
Schreib fern(size, sign) für das Farnblatt aus dem Bild oben. sign ist 1 oder −1 und sagt, wohin sich das Blatt biegt: Mit −1 ist es gespiegelt. Danach steht die Schildkröte wieder unten am Stiel und schaut wie vorher.
Kleiner als 1 zeichnet die Funktion nichts.
Sonst: ein Stück Stiel, 70 · sign nach rechts, ein halb so großes Blatt mit -sign, zurückdrehen; noch ein Stück Stiel, 70 · sign nach links, ein halb so großes Blatt mit sign, zurückdrehen.
Dann der Rest des Blatts: 7 · sign nach rechts, fern(size - 1, sign), 7 · sign zurück, und den Stiel zurück, zwei Stücke: size * 2.
Schreib fern(size, sign) für das Farnblatt aus dem Bild oben. sign ist 1 oder −1 und sagt, wohin sich das Blatt biegt: Mit −1 ist es gespiegelt. Danach steht die Schildkröte wieder unten am Stiel und schaut wie vorher.
Kleiner als 1 zeichnet die Funktion nichts.
Sonst: ein Stück Stiel, 70 · sign nach rechts, ein halb so großes Blatt mit -sign, zurückdrehen; noch ein Stück Stiel, 70 · sign nach links, ein halb so großes Blatt mit sign, zurückdrehen.
Dann der Rest des Blatts: 7 · sign nach rechts, fern(size - 1, sign), 7 · sign zurück, und den Stiel zurück, zwei Stücke: size * 2.
Schreib fern(size, sign) für das Farnblatt aus dem Bild oben. sign ist 1 oder −1 und sagt, wohin sich das Blatt biegt: Mit −1 ist es gespiegelt. Danach steht die Schildkröte wieder unten am Stiel und schaut wie vorher.
Kleiner als 1 zeichnet die Funktion nichts.
Sonst: ein Stück Stiel, 70 · sign nach rechts, ein halb so großes Blatt mit -sign, zurückdrehen; noch ein Stück Stiel, 70 · sign nach links, ein halb so großes Blatt mit sign, zurückdrehen.
Dann der Rest des Blatts: 7 · sign nach rechts, fern(size - 1, sign), 7 · sign zurück, und den Stiel zurück, zwei Stücke: size * 2.
Wacław Sierpiński hat ein Dreieck beschrieben, das aus drei halb so großen Dreiecken besteht, von denen jedes wieder aus dreien besteht:
Wacław Sierpiński (1882–1969), polnischer Mathematiker in Warschau, mit über 700 Aufsätzen und 50 Büchern. 1916 beschrieb er ein Quadrat, aus dem die Mitte fehlt, und aus jedem der acht Quadrate drumherum wieder die Mitte, ohne Ende: den Sierpinski-Teppich. Auch ein Dreieck aus Dreiecken trägt seinen Namen.
Ein Muster, das in jedem Ausschnitt wieder sich selbst enthält, heißt heute Fraktal. Dein Shader rechnet den Teppich mit einer Schleife aus vier Zeilen.
Foto: unbekannt, 1928, gemeinfrei, zugeschnitten (Wikimedia Commons)
Schreib sierpinski(size, depth) für das Dreieck aus dem Bild oben, mit Seiten der Länge size. Danach steht die Schildkröte wieder, wo sie angefangen hat, und schaut wie vorher.
Die Stufe 0 ist das Dreieck von ganz am Anfang, mit size statt 150.
Jede andere Stufe besteht aus drei Dreiecken der Stufe darunter, halb so groß: sierpinski(size / 2, depth - 1), links unten, rechts unten und oben. In Ruby size / 2.0.
Zwischen ihnen läuft die Schildkröte: die halbe Seite nach rechts für das zweite; zurück und die halbe linke Seite hinauf (60 nach links, vorwärts, 60 nach rechts) für das dritte; dann denselben Weg zurück.
Schreib sierpinski(size, depth) für das Dreieck aus dem Bild oben, mit Seiten der Länge size. Danach steht die Schildkröte wieder, wo sie angefangen hat, und schaut wie vorher.
Die Stufe 0 ist das Dreieck von ganz am Anfang, mit size statt 150.
Jede andere Stufe besteht aus drei Dreiecken der Stufe darunter, halb so groß: sierpinski(size / 2, depth - 1), links unten, rechts unten und oben. In Ruby size / 2.0.
Zwischen ihnen läuft die Schildkröte: die halbe Seite nach rechts für das zweite; zurück und die halbe linke Seite hinauf (60 nach links, vorwärts, 60 nach rechts) für das dritte; dann denselben Weg zurück.
Schreib sierpinski(size, depth) für das Dreieck aus dem Bild oben, mit Seiten der Länge size. Danach steht die Schildkröte wieder, wo sie angefangen hat, und schaut wie vorher.
Die Stufe 0 ist das Dreieck von ganz am Anfang, mit size statt 150.
Jede andere Stufe besteht aus drei Dreiecken der Stufe darunter, halb so groß: sierpinski(size / 2, depth - 1), links unten, rechts unten und oben. In Ruby size / 2.0.
Zwischen ihnen läuft die Schildkröte: die halbe Seite nach rechts für das zweite; zurück und die halbe linke Seite hinauf (60 nach links, vorwärts, 60 nach rechts) für das dritte; dann denselben Weg zurück.
Helge von Koch hat 1904 eine Kurve beschrieben, die aus vier Kurven mit einem Drittel der Länge besteht. Je höher die Stufe, desto feiner die Zacken; ein Stück von ihr sieht aus wie die ganze Kurve.
Schreib koch(size, depth) für die Koch-Kurve aus dem Bild oben: size Schritte von links nach rechts, mit so vielen Stufen, wie depth sagt.
Die Stufe 0 ist eine gerade Linie: forward(size), und fertig.
Jede andere Stufe besteht aus vier Kurven der Stufe darunter, jede ein Drittel so lang: viermal koch(size / 3, depth - 1).
Zwischen den vier Kurven: 60 Grad nach links, 120 nach rechts, 60 nach links, so wie die Zacke in der Stufe 1.
Schreib koch(size, depth) für die Koch-Kurve aus dem Bild oben: size Schritte von links nach rechts, mit so vielen Stufen, wie depth sagt.
Die Stufe 0 ist eine gerade Linie: forward(size), und fertig.
Jede andere Stufe besteht aus vier Kurven der Stufe darunter, jede ein Drittel so lang: viermal koch(size / 3, depth - 1).
Zwischen den vier Kurven: 60 Grad nach links, 120 nach rechts, 60 nach links, so wie die Zacke in der Stufe 1.
Schreib koch(size, depth) für die Koch-Kurve aus dem Bild oben: size Schritte von links nach rechts, mit so vielen Stufen, wie depth sagt.
Die Stufe 0 ist eine gerade Linie: forward(size), und fertig.
Jede andere Stufe besteht aus vier Kurven der Stufe darunter, jede ein Drittel so lang: viermal koch(size / 3, depth - 1).
Zwischen den vier Kurven: 60 Grad nach links, 120 nach rechts, 60 nach links, so wie die Zacke in der Stufe 1.
Ein Extra für Schnelle. Wer es auslässt, springt zu Dein eigener Baum.
David Hilbert hat 1891 eine Kurve beschrieben, die durch ein Quadrat läuft, ohne sich je zu kreuzen, und mit jeder Stufe jeder Stelle des Quadrats näherkommt. Ihre Stufe 1 ist ein U aus drei Linien. Jede höhere Stufe setzt vier Kurven der Stufe davor an die Ecken dieses U, verbunden durch seine drei Linien. Damit sie sich zu einer Linie verbinden, sind die erste und die letzte gespiegelt.
Schreib hilbert(level, angle, size) für die Hilbert-Kurve aus dem Bild oben: jede graue Linie size lang, angle 90. Mit -90 ist die Kurve gespiegelt.
Die Stufe 0 zeichnet nichts. Die Stufe 1 ist das U: angle nach rechts, vorwärts, angle nach links, vorwärts, angle nach links, vorwärts, angle nach rechts.
Für jede andere Stufe kommen vier Kurven der Stufe darunter in dieses U: nach der ersten Drehung, nach der zweiten, nach der zweiten Linie und vor der letzten Drehung.
Die erste und die letzte sind gespiegelt: Sie bekommen -angle, die beiden mittleren angle.
Schreib hilbert(level, angle, size) für die Hilbert-Kurve aus dem Bild oben: jede graue Linie size lang, angle 90. Mit -90 ist die Kurve gespiegelt.
Die Stufe 0 zeichnet nichts. Die Stufe 1 ist das U: angle nach rechts, vorwärts, angle nach links, vorwärts, angle nach links, vorwärts, angle nach rechts.
Für jede andere Stufe kommen vier Kurven der Stufe darunter in dieses U: nach der ersten Drehung, nach der zweiten, nach der zweiten Linie und vor der letzten Drehung.
Die erste und die letzte sind gespiegelt: Sie bekommen -angle, die beiden mittleren angle.
Schreib hilbert(level, angle, size) für die Hilbert-Kurve aus dem Bild oben: jede graue Linie size lang, angle 90. Mit -90 ist die Kurve gespiegelt.
Die Stufe 0 zeichnet nichts. Die Stufe 1 ist das U: angle nach rechts, vorwärts, angle nach links, vorwärts, angle nach links, vorwärts, angle nach rechts.
Für jede andere Stufe kommen vier Kurven der Stufe darunter in dieses U: nach der ersten Drehung, nach der zweiten, nach der zweiten Linie und vor der letzten Drehung.
Die erste und die letzte sind gespiegelt: Sie bekommen -angle, die beiden mittleren angle.
Zum Schluss ein Baum, den sich niemand vorher ausgedacht hat. Geprüft wird hier nichts: Jeder Baum ist richtig.
Lass deinen eigenen Baum wachsen, wie er dir gefällt: schief, hängend, mit drei Ästen statt zwei, im Herbst rot und gelb. Wer mag, lässt den Zufall mitbestimmen.
Fang mit deinem schönen Baum an und ändere eine Zahl nach der anderen: Winkel, Längen, Farben, die Tiefe.
Ein dritter Ast in der Mitte: ein weiterer Aufruf von tree zwischen den beiden, ohne Drehung.
Lass deinen eigenen Baum wachsen, wie er dir gefällt: schief, hängend, mit drei Ästen statt zwei, im Herbst rot und gelb. Wer mag, lässt den Zufall mitbestimmen.
Fang mit deinem schönen Baum an und ändere eine Zahl nach der anderen: Winkel, Längen, Farben, die Tiefe.
Ein dritter Ast in der Mitte: ein weiterer Aufruf von tree zwischen den beiden, ohne Drehung.
Lass deinen eigenen Baum wachsen, wie er dir gefällt: schief, hängend, mit drei Ästen statt zwei, im Herbst rot und gelb. Wer mag, lässt den Zufall mitbestimmen.
Fang mit deinem schönen Baum an und ändere eine Zahl nach der anderen: Winkel, Längen, Farben, die Tiefe.
Ein dritter Ast in der Mitte: ein weiterer Aufruf von tree zwischen den beiden, ohne Drehung.
random(15, 35) ist eine zufällige Zahl
von 15 bis 35, random(0.6, 0.8) eine Kommazahl dazwischen. Lass den Baum
dann mehrmals wachsen. Achte darauf, ob er so eher wie ein echter Baum
aussieht und welche Tiefe dafür reicht.