Blümchenwiese mit Python
Ich lerne gerade Programmieren, und zwar nicht in HTML oder CSS, sondern in einer echten Programmiersprache, in Python! Zusammen mit einem kleinen Häufchen 10- bis 14-jähriger Bengels (das einzige Mädchen hat leider schon in der 2. Stunde aufgegeben) sitze ich derzeit jeden Donnerstag für anderthalb Stunden bei Lehmanns und lasse per Python-Befehl eine kleine Schildkröte über meinen Bildschirm wandern. Den Kurs hat die Fachbuchhandlung organisiert und als sie einen Lehrer suchte, hat Andreas, der schon immer den Wunsch verspürte, Kindern mal anständig programmieren beizubringen, sofort zugesagt. Weil ich kein Kind mehr bin, bin ich offiziell seine Assistentin und da ich selbst quasi bei Null anfange, gebe ich auch Tipps, wann es zu schnell geht oder irgendetwas unklar ist.
Ein paar Stunden haben wir jetzt schon hinter uns. Wir arbeiten mit dem Buch „Python4Kids“ von Gregor Lingl und der Turtle Grafik. Die Turtle Grafik ist ein Python-Modul, das es ermöglicht, mit ein paar einfachen Befehlen eine kleine Schildkröte über den Bildschirm wandern zu lassen. Beim Wandern hinterläßt die Schildkröte Striche auf dem Untergrund und so kann man mit ihrer Hilfe Figuren und ganze Bilder malen. Man sagt der Turtle gehe 100 Schritte vorwärts, dann drehe dich um 90° und gehe wieder 100 Schritte vorwärts. Wenn man diese Gehen-und-Drehen-Sequenz viermal wiederholt, malt die Schildkröte ein Quadrat. Aber man kann es sich sparen, das viermal hinschreiben zu müssen, indem man es einmal in einer for-Schleife einbindet. Wenn man öfter Quadrate malen will, definiert man sich eine Funktion dafür. In dieser Funktion kann man auch die Parameter Größe und Farbe definieren, um Quadrate unterschiedlicher Größe und Farbe zu malen, und so weiter. So lernt man beim Malen quasi nebenbei Programmieren. Klasse!
Letzten Donnerstag konnte Andreas den Kurs nicht leiten, also hat er uns Aufgaben mitgegeben. Eine Aufgabe bestand darin, ein Skript zu schreiben, das mit der Turtle Grafik eine Blümchenwiese malt. Nach zwei Wochen schulferien-bedingerter Kurspause war das gar nicht so einfach. Okay, die Wiese mal‘ ich als großes, grünes Quadrat, das ist nicht schwer. Aber wie zum Henker malt man in Python eine Blume? Kreise, dachte ich mir, viele bunte Kreise außen für die Blütenblätter und ein gelber Kreis in der Mitte für die Staubblätter. Ich hatte schon in den vergangenen Stunden gelernt, dass man sich Programmieraufgaben am besten in kleine Häppchen zerlegt und sein Programm dann Stück für Stück erweitert und optimiert, wenn man nicht gleich sofort weiß, wie man alles umsetzen soll. Also habe ich damit angefangen, einen einzigen Kreis zu malen, wofür es die einfache Funktion circle( ) gibt. Dann habe ich einen Weg gefunden, wie ich um diesen Kreis herum nebeneinander mehrere Kreise anordnen kann. Dafür habe ich den Kreiswinkel von 360° durch die Anzahl der Blütenblätter geteilt (in meinem Falle 7), bin dann mit der Turtle immer 1/7-Kreis gelaufen, hab sie dann hin und her gedreht, um sie auszurichten, und dann noch einen Kreis gemalt. Das ganze siebenmal wiederholt und schwups war die 7-blättrige Blume fertig. Wenn man den Kreisen dann einen Radius von 10 gibt, sieht das ungefähr so aus:
def blume(): for _ in range(7): circle(10, 51) # 51 = 1/7 Kreiswinkel left(180) circle(10) right(180)
Damit die Blumen variable Größen haben können, habe ich anschließend den Parameter „groesse“ definiert, der in der Funktion blume(groesse) übergeben können werden soll. Die Größe der gesamten Blume hat den Radius der einzelnen Kreise mal 3, bzw. ist der Radius der Kreise gleich der Größe der Blume durch 3. Außerdem wollte ich verschiedenfarbige Blütenblätter, also habe ich den Parameter „farbe“ definiert, der ebenfalls in der Funktion blume(groesse, farbe) übergeben können werden soll. Jeder Kreis, der ein Blütenblatt werden soll, wird also in einer Farbe ausgefüllt, am Ende wird ein gelb gefüllter Kreis in die Mitte gemalt. Danach sah mein Code so aus:
def blume(groesse, farbe): r = groess/3 for _ in range(7): fillcolor(farbe) begin_fill() circle(r, 51) left(180) circle(r) right(180) end_fill() fillcolor("yellow") begin_fill() circle(r) end_fill()
Rufen wir jetzt also die Funktion blume(10, "red") auf, malt uns die Turtle eine rote Blume in der Größe 3x10 mit einem gelben Kreis in der Mitte. Das ganze können wir variieren, z.B. mit blume(20, "blue"). Ein bisschen bescheuert sieht das ganze noch aus, weil die Umrisse der Kreise noch als schwarze Linien zu sehen sind, dafür ergänzt man in der der Definition noch die Zeile "pencolor(farbe)" am Anfang der for-Schleife. So, nun hat aber eine Blumenwiese nicht nur eine Blume, sondern mehrere, die alle unterschiedlich groß und unterschiedlich gefärbt sind. Also dachte ich mir, setze ich für die Größe eine Zufallszahl und für die Farbe eine Zufallsfarbe. Für Zufallszahlen gibt es schon die vordefinierte Funktion randint( ), für Zufallsfarben mußte ich eine neue Funktion definieren, die ich randcolor( ) genannt habe. Dafür habe ich mir zunächst eine Liste mit Farben erstellt und dann die Funktion einen zufälligen Farbstring zurückgeben lassen, indem ich mit randint( ) ein zufälliges Element aus der Liste ausgewählt habe. Das sieht so aus:
farbliste = ("white", "red", "orange", "blue") def randcolor(): return farbliste[randint(0,len(farbliste)-1)]
Man gibt das Element einer Liste in eckigen Klammern [ ] an, wobei das 1. Element als 0 und das letzte als Summe der Elemente - 1 indiziert wird. Um also die Farbe "blue" auszuwählen, würde man farbliste[3] aufrufen. Um das ein bisschen zufälliger zu machen, rufe ich anstelle einer Zahl die Funktion randint( ) auf, die eine Zahl zwischen Null und der Länge der Farbliste - 1 wählen soll. Rufe ich nun also die Funktion blume(randint(10, 100), randcolor()) auf, bekomme ich eine Blume in einer zufälligen Größe zwischen 10 und 100 in einer zufälligen Farbe meiner Farbliste. Toll! Jetzt wollte ich mehrere zufällige Blumen an zufälligen Positionen auf dem Bildschirm verteilen. Ich mußte also in einer for-Schleife mehrmals meine Blumenfunktion aufrufen und nach jedem Aufruf sofort zufällig irgendwohin springen. Für den Sprung definierte ich mir die Funktion jump( ), die dafür sorgt, dass der Stift der Schildkröte angehoben wird, sie sich dann in einem Winkel dreht, dann eine Schrittfolge vorwärts läuft, sich wieder in die Ausgangsposition dreht und den Stift absetzt. Das Ganze mit in die for-Schleife gepackt und zufällige Werte übergeben, machte viele bunte Blumen an unterschiedlichen Stellen und sah so aus:
def jump(weite, winkel=0): penup() left(winkel) forward(weite) right(winkel) pendown() for _ in range(10): blume(randint(10, 30), randcolor()) jump(rantint(10, 100), rantint(0, 360))
Das einzige Problem an diesem Code ist der Zufall. Der ist zwar zufällig, aber dadurch passiert es auch, dass zufällig fünfmal hintereinander dieselbe Farbe ausgewählt wird und sich die Blumen an gewissen Positionen clustern. Es gibt also beim Zufall keine gleichmäßige Verteilung. Verdammt! Ich habe mich also entschieden, mich von meiner Funktion randcolor( ) zu verabschieden und sie zu verwerfen. Stattdessen wollte ich für die Farbe der Blumen lieber nacheinander durch meine Farbliste gehen, so dass eine Farbe erst dann wiederholt wird, wenn alle anderen Farben schon gemalt wurden. Schwieriger war es, die Blumen gleichmäßiger auf der Wiese zu verteilen. Ich dachte mir, ich müßte die Turtle nach jeder Blume wieder zurück in die Ausgangsposition holen und sie für die nächste Blume an eine absolute Position im Koordinatensystem schicken, die zufällig gewählt ist. Ich lernte, dass es dafür die vordefinierten Funktionen home( ) und goto(x, y) gibt. Das vereinfachte auch an anderen Stellen meinen Code, weil ich weder für die Blumen, noch für die Wiese irgendwie wild herumspringen, laufen, stiftheben und drehen mußte. Ich konnte mich also auch von der Funktion jump( ) verabschieden und dadurch meinen Code optimieren.
Obwohl noch immer einige Blumen überlappten waren sie jetzt viel besser verteilt und insgesamt bunter. Was mir noch nicht so gefiel, waren die Blumen selbst, man konnte zwischen den äußeren Blütenblättern und dem inneren Kreis stellenweise noch das grün der Wiese durchscheinen sehen. Der Kreis in der Mitte war einfach zu klein, ich brauchte einen größeren Kreis. Da aber Kreise nicht vom Mittelpunkt aus gemalt werden, sondern von der Position aus in einer Linkskurve, mußte ich der Schildkröte beibringen, erst ein bisschen nach außen zu springen und dann mit dem Kreis zu beginnen. Es war gar nicht einfach, ihr beizubringen, nicht zu weit nach außen zu springen und den Kreis in der Mitte bei kleinen Blumen nicht zu groß zu machen. Aber nach einigem Rumprobieren habe ich eine Lösung gefunden und in meine ursprüngliche Blumen-Funktion implementiert. Das Ergebnis könnte z.B. so aussehen:
Und der Code dazu ist folgender:
Damit habe ich meine erste komplexere Programmieraufgabe erfüllt und ein Python-Skript geschrieben, das mir 70 bunte Blumen auf eine grüne Wiese malt. Nächster Schritt wäre, das ganze irgendwie in Perspektive zu bringen und nicht nur als Draufsicht zu realisieren. Aber das heb' ich mir für's nächste Mal auf. Ich merke immer mehr, wieviel Spaß Programmieren macht, wie kreativ und herausfordernd es ist. Man hat viele kleine Aufgaben und knobelt dann an der besten Lösung und wenn man die gefunden hat, betrachtet man mit Stolz sein Werk. Ist eigentlich genau wie Dichten oder Komponieren, nur eben in einem anderen Zeichensystem.
Mai 9th, 2011 16:32
Na bitte! Hab ich doch immer schon gesagt, dass man fürs Programmieren auch viel Kreativität braucht.
Gruß Tilly
November 19th, 2011 10:03
HTML und CSS sind Auszeichnungssprachen und keine Programmiersprachen 😉
November 19th, 2011 11:06
Was meinst du, warum ich schrieb, dass ich jetzt eine richtige Programmiersprache lerne und nicht sowas wie HTML und CSS?
November 20th, 2011 19:03
Meinen tue ich gar nichts, aber wenn der erste Satz lautet: „Ich lerne gerade Programmieren, und zwar nicht in HTML oder CSS, sondern in einer echten Programmiersprache“, dann ist es so als schreibe jemand: „Ich lerne gerade Autofahren, aber nicht auf einem Pferd oder einer Kuh, sondern in einem Toyota.“
😀
November 20th, 2011 20:40
Dieser Einwand ist natürlich völlig korrekt. Nur geht es in diesem Blog ja nicht primär ums Programmieren, weshalb ich davon ausgehe, dass der Großteil meines Leserpublikums den Unterschied sowieso nicht kennt. Es versteht „Programmieren“ eher umgangssprachlich, wie das Analogon „Fortbewegen“, das eben auch mit einer Kuh oder einem Pferd geht. Insofern ist mein „aber“ eher als Hinweis darauf gemeint gewesen, dass es einen Unterschied gibt, den zu erläutern ich aber für diesen Artikel nicht nötig fand. Wenn du das gerne übernehmen möchtest, weil es dir wichtig erscheint, tue dir keinen Zwang an. 😉
März 2nd, 2012 17:27
Hallo
wow das hast du aber toll hinbekommen
kann ich auch eine einzelne blume NUR
mit turtle machen????
was kann ich damit noch relativ einfaches machen?
wäre nett wenn ihr mir helft
Mona
April 25th, 2012 11:42
Hallo Mona, also im Grunde genommen kannst du der Turtle alles erzählen, was sie malen soll und wenn du’s richtig programmiert hast, tut sie es einfach. Die Blumenwiese besteht ja aus ganz vielen einzelnen Blumen, in dem Programm wird dafür die Funktion blume() immer wieder ausgeführt. Die Funktion kannst du selbst definieren (meine Blumen bestehen bspw. aus 7 Kreisen, die im Kreis angeordnet und dann gefüllt werden) und dann sooft aufrufen, wie du möchtest. Die Wikipedia weiß mal wieder mehr: https://en.wikipedia.org/wiki/Turtle_graphics LG, LeV.
Mai 10th, 2017 11:16
Alles Veraltet