Block B · 5 Samstage

Die Schildkröte bekommt Sinne

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.

Die eine große Idee

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.

Dein Weg

0 von 5 Stationen geschafft

Erst mal anschauen: Was macht 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.

Die Wenn-Maschine

120

      

Zwei Bedingungen gleichzeitig: and und or

Der grüne Bereich ist der Mittelstreifen von −100 bis 100. Schieb die Schildkröte hin und her und schalte zwischen and und or um. Bei einem der beiden ist der grüne Bereich auf einmal überall. Findest du heraus, warum?

40

      

Die Falle, in die alle treten

= 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.

Station 1

Zufalls-Stadt

Dein Programm bekommt eine Laune.

Das wird es tun

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.

Zerlege-Tafel

Die große Aufgabe heißt „Stadt“. Zu groß. Also kleiner machen, bis jedes Stück in eine Zeile passt:

  1. Eine Stadt ist eine Reihe von Häusern → eine Schleife, die du schon kennst.
  2. Ein Haus ist eine Funktion mit zwei Reglern: haus(breite, hoehe) → kennst du auch.
  3. Ein Haus besteht aus linker Wand – Dach – rechter Wand.
  4. Das Dach ist das Einzige, was neu ist: es gibt zwei Sorten. Genau dafür ist if da.
  5. Die Zahlen (Breite, Höhe, Dachsorte) kommen nicht von dir, sondern vom Würfel.

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.

Das Gerüst

#  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.

Dreh an den Schrauben

Fehler-Detektiv

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":

Fertig, wenn…

Station 2

Flummi

Die Schildkröte merkt, wo sie ist.

Das wird es tun

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.

Der wichtigste Satz dieser fünf Samstage

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.

Zerlege-Tafel

  1. Torkeln = einen Schritt vor, dann ein kleines zufälliges Stück drehen.
  2. Das 2000× wiederholen → Schleife, kennst du.
  3. Nach jedem Schritt fragen: Bin ich noch im Fenster?
  4. „Draußen“ sind vier Fälle: zu weit rechts, links, oben, unten. Vier Bedingungen, eine reicht schon → or.
  5. Wenn draußen: zur Mitte drehen und weiterlaufen. (Nicht einfach umdrehen — warum nicht, siehst du gleich im Experiment.)

Das Gerüst

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()

Das Experiment zu Zeile (3)

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.

Dreh an den Schrauben

Fehler-Detektiv

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:

Fertig, wenn…

Station 3

Zeichen-Maschine

Jetzt steuerst du — und ein Wächter passt auf.

Das wird es tun

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.

Trick: der Funktionsname ohne Klammern

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.

Zerlege-Tafel

  1. Vier Tasten → vier Funktionen. Jede dreht in eine Himmelsrichtung und fährt los.
  2. Die vier Funktionen sind gleich gebaut und unterscheiden sich in einer Zahl.
  3. Der Wächter prüft nach dem Zug, ob die Schildkröte draußen ist — und nimmt den Zug zurück.
  4. Der Mittelstreifen ist ein Bereich: größer als −100 und kleiner als 100 → and.
  5. Am Ende: Tasten anmelden, listen(), fertig.

Das Gerüst

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()

Beobachtungsaufgabe

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?

Dreh an den Schrauben

Wenn nichts passiert

An dieser Station streikt der Rechner bei fast allen einmal. Geh die Liste von oben nach unten durch:

  1. Steht screen.listen() da? Ohne das hört niemand zu.
  2. Steht bei onkey ein Funktionsname ohne Klammern?
  3. Hast du einmal ins Turtle-Fenster geklickt? Tasten gehen immer an das Fenster, das gerade vorne ist — und das ist oft noch Thonny.
  4. Steht turtle.done() als letzte Zeile?
  5. Heißen die Tasten genau "Up", "Down", "Left", "Right" — groß geschrieben, in Anführungszeichen?

Diese fünf Punkte erwischen so gut wie jeden Fall.

Fertig, wenn…

Station 4

Punkte-Jagd

Ein richtiges Spiel. Mit Gegner.

Das wird es tun

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.

Trick: vier Türen, ein Zimmer

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.

Trick: global — der Zettel-Trick

Eine 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.

Zerlege-Tafel

  1. Vier Schildkröten mit vier Rollen: Spieler, Jäger, Ziel und eine, die nur schreibt.
  2. Das Ziel an einen Zufallsort setzen → eigene Funktion, wird später wieder gebraucht.
  3. Der Punktestand anzeigen → eigene Funktion: alten Text weg, neuen hin.
  4. Ein Zug besteht aus vier Dingen in dieser Reihenfolge: ich laufe · Jäger läuft · Ziel erwischt? · ich erwischt?
  5. „Berührt“ heißt nicht „genau derselbe Punkt“, sondern nah genug → distance(...) < 25.
  6. Der Jäger muss nicht wissen, wohin — er fragt: towards(spieler).

Das Gerüst

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.

Dreh an den Schrauben

Fehler-Detektiv

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()))

Fertig, wenn…

Station 5

Mein eigenes Spiel

Projekt-Samstag. Nichts Neues mehr — nur noch deins.

Die Regel

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.

Die Liste

UpgradeWas du dafür brauchstAufwand
Zeitlimit — nach 60 Sekunden ist Schlussimport time, eine Startzeit, ein if●●○
Level — alle 5 Punkte wird der Jäger schneller%, eine Variable, global●○○
Zweiter Jäger von der anderen Eckeeine Schildkröte mehr, or●○○
Goldenes Ziel — selten, aber 10 Punkterandint, if, Farbwechsel●●○
Tarnkappe — drei Sekunden unsichtbar und unfangbartime, eine Variable, zwei if●●●
Hindernisse — Klötze, durch die keiner darfListe, Schleife, distance●●●
Highscore — die beste Zahl bleibt steheneine Variable, ein if●○○
Eigener Look — Hintergrund, Farben, Spielfeld-Rahmenbgcolor, eine Mal-Schildkröte●○○
Zwei Spieler — WASD gegen Pfeiltastenvier Funktionen mehr, onkey●●●

Erst planen, dann tippen

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.

Die letzte Frage des Blocks

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.

Spickzettel

Die neuen Bausteine

Nur die Form. Was hineinkommt, findest du selbst heraus.

Entscheiden
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.

Vergleichen und verbinden
> < >= <= == !=

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).

Zufall
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.

Die Schildkröte ausfragen
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.

Tasten
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.

Zahlen und Text
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.