Bis jetzt hat dein Programm immer dasselbe gemalt. Jetzt lernt es ein neues Wort: wenn. Damit kann es sich umschauen, selbst entscheiden — und am Ende spielt jemand anders damit.
Alle deine Programme bis jetzt waren wie eine Spieluhr: aufziehen, loslassen, immer dieselbe Melodie. Sie hatten keine Sinnesorgane.
Ein if ist ein Sinnesorgan. Das Programm
fragt: „Wie ist es gerade?“ — und macht dann das eine oder das andere.
Fünf Samstage, fünf Projekte, und am Ende hast du ein Spiel, in das dein Nachbar spielt.
0 von 5 Stationen geschafft
if eigentlich?Zieh am Regler. Das Programm darunter ist echt — es entscheidet bei jeder Zahl neu, welchen Weg es nimmt. Der grün markierte Weg ist der, der gerade läuft.
= ist eins, == ist
zwei. Mit einem Gleichheitszeichen setzt du etwas
(punkte = 0 — „die Punkte sollen null sein“). Mit zwei
Gleichheitszeichen fragst du etwas (if punkte == 0: —
„sind die Punkte null?“). Im if stehen immer zwei.
Dein Programm bekommt eine Laune.
Eine Straße aus zehn Häusern. Jedes Haus würfelt seine Breite, seine Höhe und sein Dach: flach oder spitz. Drück zweimal auf Start — und du bekommst zwei verschiedene Städte aus demselben Programm.
Am Ende der Stunde drucken wir drei Läufe von dir aus und hängen sie nebeneinander. Derselbe Code. Drei Städte.
Die große Aufgabe heißt „Stadt“. Zu groß. Also kleiner machen, bis jedes Stück in eine Zeile passt:
haus(breite, hoehe) → kennst du auch.if da.Merk dir Schritt 4: Nur ein Stück des Hauses ist wirklich neu. Alles andere kannst du schon. So fühlt sich Zerlegen an, wenn es gut läuft.
# Jede Lücke ist eine Aufgabe. Die Kommentare sagen, was dort hin muss. import turtle import random # (1) die neue Kiste: der Wuerfel screen = turtle.Screen() screen.setup(700, 700) t = turtle.Turtle() t.speed(0) def haus(breite, hoehe): # (2) Linke Wand hoch. Die eine Zeile schenke ich dir - # an ihr siehst du das Muster: drehen, laufen, zurueckdrehen. t.left(90); t.forward(hoehe); t.right(90) # (3) Jetzt wuerfelt das Haus sein Dach. 1 oder 2. wurf = random.randint(..., ...) if wurf ... 1: # (4) FLACHDACH: ein einziger Strich nach rechts, so lang wie breite. ... else: # (5) SPITZDACH: schraeg hoch zur Spitze, schraeg runter. # Das ist das Dreieck aus Termin 1! Drei Zahlen brauchst du: # left(60) - forward(?) - right(120) - forward(?) - left(60) # Welche Laenge? Probier breite aus und schau, ob das Dach passt. ... # (6) Rechte Wand runter - das Gegenteil von Zeile (2). # Wenn du es richtig machst, steht die Schildkroete danach # unten rechts und schaut nach rechts: direkt am naechsten Haus. ... t.penup(); t.goto(-320, -150); t.pendown() for i in range(10): # (7) Jedes Haus wuerfelt seine eigenen Masse. # Breite zwischen 30 und 60, Hoehe zwischen 60 und 200. haus(..., ...) turtle.done()
Wenn die Häuser nach dem Dach verrutschen, liegt es fast immer an Schritt 6 — nicht am Dach.
randint(1, 3) ein und frag in (4) nach == 1.
Wie viele Häuser haben jetzt ein Flachdach? Ungefähr jedes dritte. Warum?elif —
schau unten bei den Bausteinen nach.farben[random.randint(0, 3)].
Listen kennst du aus Termin 3.%.screen.tracer(0) und danach screen.update().
Die Stadt erscheint auf einen Schlag.Diese zwei Zeilen hat jemand abgetippt. Beide laufen — aber eine macht etwas Falsches, ohne sich zu beschweren. Schreib auf, was bei jeder passiert, bevor du sie ausprobierst:
if wurf = 1: if wurf == "1":
randint(1, 2) steht.Die Schildkröte merkt, wo sie ist.
Die Schildkröte läuft 2000 Schritte ganz allein los und torkelt dabei. Jedes Mal, wenn sie an eine Wand kommt, prallt sie ab. Nach einer halben Minute ist das ganze Fenster voll mit einem Knäuel, das kein Mensch zeichnen könnte — und bei jedem von euch sieht es anders aus.
Bis jetzt hat dein Programm der Schildkröte nur Befehle
gegeben. Mit t.xcor() stellt es ihr zum ersten Mal eine
Frage: „Wo stehst du gerade?“ Und sie antwortet mit einer Zahl.
Ab hier kann ein Programm auf die Welt reagieren.
or.import turtle import random screen = turtle.Screen() screen.setup(700, 700) t = turtle.Turtle() t.speed(0); t.pensize(2) for schritt in range(2000): t.forward(10) # (1) Torkeln: ein kleines zufaelliges Stueck drehen, # nach links UND nach rechts. Welche zwei Zahlen gehoeren # in randint, damit es in beide Richtungen geht? t.left(random.randint(..., ...)) # (2) Der Fuehler. Vier Faelle, eine Zeile, verbunden mit or. # Das Feld geht von -280 bis 280 - in beide Richtungen. if t.xcor() > 280 or ... or ... or ...: # (3) Eine einzige Zeile: "dreh dich zur Mitte". # Du brauchst zwei Befehle ineinander - einer fragt nach # dem Winkel zur Mitte (0, 0), der andere dreht sie dorthin. # Beide stehen unten im Spickzettel. ... # (4) Himmel und Erde: oberhalb der Mitte eine Farbe, # unterhalb eine andere. Was fragst du ab - xcor oder ycor? if ...: ... else: ... turtle.done()
Die erste Idee, auf die alle kommen, ist t.left(180) — einfach umdrehen.
Bau sie ein und lass das Programm fünfmal laufen. Bei vier Läufen sieht
alles gut aus. Bei einem reißt es aus: Striche laufen aus dem Fenster.
Warum? Stell dir vor, die Schildkröte läuft fast parallel zur Wand, wenn sie anstößt. Dreht sie sich um 180°, läuft sie immer noch an der Wand entlang — nur andersherum. Sie kommt kein Stück ins Feld zurück und torkelt mit der Zeit immer weiter hinaus.
Deshalb fragt die richtige Lösung nicht „wohin schaue ich
gerade?“, sondern „wo ist die Mitte?“. Nachgerechnet,
60 Läufe à 2000 Schritte: mit der Drehung zur Mitte kommt sie nie weiter als 290
hinaus — mit left(180) im schlimmsten Lauf bis 422. Das Fenster endet
bei 350.
randint(-25, 25) → randint(-90, 90). Aus dem Knäuel wird Wolle.80 statt 280. Es entsteht ein dicker Fleck mit scharfer Kante.t.forward(40) direkt unter die Drehung zur Mitte. Sie springt dann
nach jedem Abprall ein Stück ins Feld hinein: in der Mitte wird das Bild dichter, am Rand
luftiger. Von 100 Rasterfeldern füllt sie damit etwa 62 — ohne den Sprung 83.
Welches gefällt dir besser?and: links oben, rechts oben, links unten, rechts unten.screen.tracer(0) davor, screen.update() danach — und 20000 Schritte
statt 2000. Jetzt wird es dunkel.Drei Varianten der Fühler-Zeile. Nur eine ist richtig. Sag bei den anderen zwei vorher, was die Schildkröte stattdessen tun wird:
if t.xcor or t.ycor > 280: if t.xcor() > 280 and t.ycor() > 280: if t.xcor() > 280 or t.xcor() < -280:
or steht und nicht and.Jetzt steuerst du — und ein Wächter passt auf.
Pfeiltasten. Die Schildkröte fährt und zieht einen Strich. Das Feld hat unsichtbare Wände, über die sie nicht hinauskommt. Und im Mittelstreifen malt sie grün.
Die Probe: Dein Nachbar setzt sich an deinen Rechner und schreibt mit deinem Programm seinen Namen. Wenn das klappt, hast du keine Zeichnung gebaut, sondern ein Werkzeug.
Bis jetzt hast du Funktionen gerufen: hoch(). Die Klammern heißen
„jetzt sofort ausführen“.
Bei screen.onkey(hoch, "Up") steht hoch
ohne Klammern. Du sagst nicht „mach das jetzt“, sondern
„merk dir diese Funktion für später“. Schreibst du die Klammern hin, passiert sie
einmal beim Start und danach nie wieder. Das ist der häufigste Fehler an dieser Station.
and.listen(), fertig.import turtle screen = turtle.Screen() screen.setup(700, 700) t = turtle.Turtle() t.pensize(3) # Der Kompass (kennst du aus Termin 1): # 0 = rechts 90 = oben 180 = links 270 = unten def hoch(): t.setheading(90) t.forward(20) waechter() streifen() def runter(): # (1) Genau wie hoch(). EINE Zahl ist anders. ... def links(): ... def rechts(): ... def waechter(): # (2) Erst machen lassen, dann pruefen, bei Verstoss zuruecknehmen. # Dieselben vier Faelle wie beim Flummi - mit or verbunden. if ...: t.backward(20) def streifen(): # (3) Gruen, WENN x zwischen -100 und 100 liegt. # Das sind zwei Bedingungen, die BEIDE stimmen muessen. if ... and ...: t.pencolor("#129B72") else: ... def putzen(): # (4) alles weg und zurueck in die Mitte ... # (5) Tasten anmelden. Funktionsname OHNE Klammern! screen.onkey(hoch, "Up") screen.onkey(..., "Down") screen.onkey(..., ...) screen.onkey(..., ...) screen.onkey(putzen, "c") screen.listen() # (6) ohne diese Zeile tut keine Taste etwas turtle.done()
Fahr absichtlich in die Wand und schau genau hin: über dem Rand steht ein kurzer Stummel. Warum zeichnet der Wächter den, obwohl er den Zug doch zurücknimmt? Was müsstest du tun, damit er nicht zu sehen ist?
"space" hebt den Stift (t.penup()) — oder senkt ihn wieder.
Woher weiß das Programm, was gerade dran ist? Hier brauchst du ein if über
t.isdown().1 bis 4 für vier Farben.t.forward(20) → t.forward(5). Viel feiner, aber viel mehr Drücken.and.t.distance(0, 0) gibt dir die Zahl.An dieser Station streikt der Rechner bei fast allen einmal. Geh die Liste von oben nach unten durch:
screen.listen() da? Ohne das hört niemand zu.onkey ein Funktionsname ohne Klammern?turtle.done() als letzte Zeile?"Up", "Down", "Left",
"Right" — groß geschrieben, in Anführungszeichen?Diese fünf Punkte erwischen so gut wie jeden Fall.
Ein richtiges Spiel. Mit Gegner.
Du bist die blaue Schildkröte und sammelst Punkte ein. Jeder Punkt springt nach dem Einsammeln an eine neue, zufällige Stelle. Die rote Schildkröte jagt dich — sie bewegt sich immer dann, wenn du dich bewegst, aber nur halb so weit. Oben steht dein Punktestand. Erwischt sie dich, ist Schluss.
Das ist ein Spiel, das man gewinnen und verlieren kann. Ich habe es ausprobiert:
mit jaeger.forward(10) schafft man zehn Punkte in etwa zwei von drei Spielen.
Setz die Zahl auf 20 — also genauso schnell wie du — und du
verlierst immer. Überleg dir, warum.
Vier Tasten bedeuten vier Funktionen. Aber der ganze Spielablauf — ich laufe, der Jäger läuft, Punkt getroffen?, erwischt? — ist bei allen vier genau derselbe. Den willst du nicht viermal abschreiben.
Also: eine Funktion zug(richtung), die alles
macht, und vier winzige Funktionen, die sie mit verschiedenen Zahlen rufen. Du kennst das
schon — es ist derselbe Regler-Trick wie bei haus(breite, hoehe).
Nur sieht man hier zum ersten Mal, wie viel Arbeit er spart.
global — der Zettel-TrickEine Funktion darf von außen lesen, aber nichts von außen
ändern — sie macht sich sonst heimlich eine eigene Kopie, und draußen bleibt
alles beim Alten. Deine Punkte stehen aber draußen, und zug() muss sie
hochzählen. global punkte als erste Zeile der Funktion ist die
Erlaubnis: „ich meine die Zahl von draußen.“ Vergisst du sie, bleibt der
Punktestand für immer auf 0 — und es gibt keine Fehlermeldung. Lass es einmal weg und
sieh es dir an.
distance(...) < 25.towards(spieler).import turtle import random screen = turtle.Screen() screen.setup(700, 700) # (1) Vier Schildkroeten. Die erste schenke ich dir. spieler = turtle.Turtle() spieler.shape("turtle"); spieler.color("#65168E"); spieler.penup() jaeger = ... # rot, Form "turtle", penup ziel = ... # orange, Form "circle", penup anzeige = ... # penup, hideturtle, oben hinstellen jaeger.goto(-280, -280) anzeige.goto(-320, 300) punkte = 0 def neues_ziel(): # (2) Das Ziel an einen Zufallsort zwischen -270 und 270 setzen. # Zwei Zufallszahlen braucht es - x und y. ... def zeige_punkte(): # (3) Erst den alten Text wegwischen: anzeige.clear() # Dann schreiben. ACHTUNG: write kann Text und Zahl nicht # zusammenkleben - die Zahl muss erst mit str(...) zu Text werden. ... def zug(richtung): global punkte # (4) der Zettel-Trick # (5) ich laufe spieler.setheading(richtung) spieler.forward(20) # (6) der Jaeger laeuft mit. Er fragt, wo ich bin, dreht sich # dorthin und macht einen halb so grossen Schritt. jaeger.setheading(jaeger.towards(...)) jaeger.forward(...) # (7) Ziel erwischt? Dann: Punkt dazu, neues Ziel, Anzeige neu. if spieler.distance(ziel) < 25: punkte = ... ... ... # (8) Selbst erwischt? Dann Schlussmeldung in die Mitte schreiben. if ...: ... # (9) Vier Tueren, ein Zimmer: jede Taste ruft zug() mit ihrer Zahl. def hoch(): zug(90) def runter(): zug(...) def links(): zug(...) def rechts(): zug(...) screen.onkey(hoch, "Up") ... neues_ziel() zeige_punkte() screen.listen() turtle.done()
Baue in dieser Reihenfolge und teste nach jedem Stück: erst (1) — vier Schildkröten stehen da. Dann (5) — ich kann fahren. Dann (2) und (7) — Punkte sammeln geht. Erst zum Schluss (6) und (8) — der Jäger. Wer alles auf einmal tippt und dann startet, sucht danach eine Stunde.
% — beides kennst du aus Termin 3. Das Spiel wird deutlich leichter.or.distance zu jedem Klotz — am besten mit einer Liste.Jede dieser drei Zeilen ergibt einen Fehler, der sich anders anfühlt. Ordne zu: einer stürzt ab, einer tut nichts Sichtbares, einer macht das Spiel kaputt, ohne zu meckern.
anzeige.write("Punkte: " + punkte) if spieler.distance(ziel) < 25: punkte + 1 jaeger.setheading(jaeger.towards(spieler()))
Projekt-Samstag. Nichts Neues mehr — nur noch deins.
Du nimmst dein Spiel von Station 4 und baust drei Sachen aus der Liste unten ein. Welche, entscheidest du. Eine Bedingung: Du musst zu jeder sagen können, warum du sie ausgesucht hast und wie sie funktioniert.
Am Ende ist Spiel-Messe. Jeder stellt sein Spiel auf, alle gehen herum und spielen die Spiele der anderen. Gewinnt niemand, aber jeder merkt sofort, ob sein Spiel Spaß macht.
| Upgrade | Was du dafür brauchst | Aufwand |
|---|---|---|
| Zeitlimit — nach 60 Sekunden ist Schluss | import time, eine Startzeit, ein if | ●●○ |
| Level — alle 5 Punkte wird der Jäger schneller | %, eine Variable, global | ●○○ |
| Zweiter Jäger von der anderen Ecke | eine Schildkröte mehr, or | ●○○ |
| Goldenes Ziel — selten, aber 10 Punkte | randint, if, Farbwechsel | ●●○ |
| Tarnkappe — drei Sekunden unsichtbar und unfangbar | time, eine Variable, zwei if | ●●● |
| Hindernisse — Klötze, durch die keiner darf | Liste, Schleife, distance | ●●● |
| Highscore — die beste Zahl bleibt stehen | eine Variable, ein if | ●○○ |
| Eigener Look — Hintergrund, Farben, Spielfeld-Rahmen | bgcolor, eine Mal-Schildkröte | ●○○ |
| Zwei Spieler — WASD gegen Pfeiltasten | vier Funktionen mehr, onkey | ●●● |
Schreib die drei Upgrades auf ein Blatt und zerlege jedes in kleine Schritte — genau so, wie es in den Zerlege-Tafeln der letzten vier Stationen stand. Dann baust du eins fertig und testest. Dann das nächste.
Wer alle drei gleichzeitig anfängt, hat am Ende drei halbe und kein ganzes.
Schau dir dein Spiel an und suche alle if darin.
Streich eines davon im Kopf weg: Was kann dein Spiel dann nicht mehr? Und jetzt überleg,
wie das Spiel ohne jedes if wäre. Das ist genau der Punkt,
an dem du vor fünf Samstagen gestanden hast.
Nur die Form. Was hineinkommt, findest du selbst heraus.
if bedingung:
Alles, was eingerückt darunter steht, passiert nur, wenn die Bedingung stimmt. Der Doppelpunkt gehört dazu. Die Einrückung ist nicht Deko — sie ist die Information, was dazugehört.
else:
Der andere Weg. Nur einer der beiden Wege läuft, niemals beide.
elif bedingung:
Ein dritter, vierter, fünfter Weg. Wird von oben nach unten geprüft, der erste passende gewinnt, danach schaut Python nicht mehr weiter.
> < >= <= == !=
größer · kleiner · größer oder gleich · kleiner oder gleich ·
gleich · ungleich. == hat zwei Zeichen, = eins —
das sind zwei völlig verschiedene Dinge.
and or
and: beide müssen stimmen. or: eine reicht. Gebraucht, sobald
du einen Bereich abfragst (and) oder mehrere Fälle auf
einmal (or).
import random
Einmal oben hinschreiben, dann ist die Würfel-Kiste offen.
random.randint(1, 6)
Eine ganze Zufallszahl. Beide Zahlen in der Klammer können herauskommen — die 1 und die 6 auch.
random.choice(liste)
Zieht einen Eintrag aus einer Liste. Praktisch für Farben.
t.xcor() t.ycor()
Wo stehe ich? Gibt eine Zahl zurück. Die Klammern müssen dran — es ist eine Frage, und Fragen werden gerufen.
t.distance(andere)
Wie weit ist es bis zu einer anderen Schildkröte? Geht auch mit einem Ort:
t.distance(0, 0).
t.towards(andere)
In welche Richtung müsste ich schauen, um dorthin zu sehen? Zusammen mit
setheading wird daraus ein Verfolger.
t.setheading(90)
Dreh dich in eine feste Richtung — nicht um einen Winkel weiter. 0 = rechts, 90 = oben, 180 = links, 270 = unten.
t.backward(20)
Rückwärts, ohne sich zu drehen. Das Werkzeug des Wächters.
screen.onkey(funktion, "Up")
Merk dir: wenn diese Taste kommt, ruf diese Funktion. Der Name steht
ohne Klammern da. Tastennamen:
"Up", "Down", "Left", "Right",
"space", und einzelne Buchstaben wie "c".
screen.listen()
Ab jetzt wird auf Tasten gehört. Ohne diese Zeile passiert gar nichts.
turtle.done()
Letzte Zeile. Hält das Fenster offen und wartet auf dich.
global punkte
Erste Zeile in einer Funktion, die eine Zahl von draußen verändern will.
t.write("Punkte: " + str(punkte))
Schreibt Text aufs Feld. str(...) macht aus einer Zahl Text — ohne
das gibt es Streit, weil Python Text und Zahl nicht zusammenkleben will.
t.clear()
Löscht alles, was diese Schildkröte gemalt hat — die anderen bleiben stehen. Darum bekommt die Anzeige eine eigene Schildkröte.