Zum Inhalt springen
BetaEN
Lektion 23 von 35Python

Python · Lektion 23 · 45 Minuten

Projekt: Tic-Tac-Toe

Das lernst du

  • Ein Spielfeld als Liste von Listen darstellen
  • Reihen, Spalten und Diagonalen prüfen
  • Ein Spiel in übersichtliche Funktionen zerlegen

Ein Feld aus Listen

Ein Tic-Tac-Toe-Feld hat 3 × 3 Kästchen. In Python baut man so etwas als Liste von Listen – eine Liste mit drei Zeilen, jede Zeile eine Liste mit drei Feldern:

feld = [
    ["X", "O", "X"],
    [" ", "X", "O"],
    ["O", " ", "X"],
]
print(feld[0][2])     # Zeile 0, Spalte 2
print(feld[1])        # die ganze mittlere Zeile

Der erste Index wählt die Zeile, der zweite die Spalte.

Das Feld schön anzeigen

def zeichnen(feld):
    for nr, zeile in enumerate(feld):
        print(" " + " | ".join(zeile))
        if nr < 2:
            print("---+---+---")


zeichnen([["X", "O", "X"], [" ", "X", "O"], ["O", " ", "X"]])

Wann hat jemand gewonnen?

Es gibt acht Gewinn-Linien: drei Zeilen, drei Spalten und zwei Diagonalen. Ein guter Trick: Sammle alle acht Linien in einer Liste und prüfe sie danach alle mit derselben Schleife – statt acht einzelne if-Abfragen zu schreiben.

a, b, c = "X", "X", "X"
print(a == b == c)        # Python kann Vergleiche verketten!
print("O" == "O" == "X")

Das ganze Spiel

Mit deiner Funktion gewinner wird daraus ein Spiel für zwei Personen:

def gewinner(feld):
    linien = [feld[i] for i in range(3)] + [[feld[0][i], feld[1][i], feld[2][i]] for i in range(3)]
    linien += [[feld[0][0], feld[1][1], feld[2][2]], [feld[0][2], feld[1][1], feld[2][0]]]
    for linie in linien:
        if linie[0] != " " and linie[0] == linie[1] == linie[2]:
            return linie[0]
    return None


feld = [[" "] * 3 for _ in range(3)]
spieler = "X"
for zug in range(9):
    for zeile in feld:
        print(" " + " | ".join(zeile))
    # So lange fragen, bis eine Zahl von 1 bis 9 kommt
    while True:
        eingabe = input(f"{spieler} – Feld 1 bis 9: ")
        try:
            nummer = int(eingabe) - 1
        except ValueError:
            print("Bitte eine Zahl eintippen.")
            continue
        if 0 <= nummer <= 8:
            break
        print("Nur Felder von 1 bis 9!")
    feld[nummer // 3][nummer % 3] = spieler
    if gewinner(feld):
        print(spieler, "gewinnt!")
        break
    spieler = "O" if spieler == "X" else "X"
else:
    print("Unentschieden!")

Weiterbauen: Prüf, ob das Feld schon belegt ist. Oder bau einen Computer-Gegner, der mit random.choice ein freies Feld wählt.

Deine Aufgabe

Jetzt bist du dran

Schreib die Funktion gewinner(feld). Das Feld ist eine Liste aus drei Zeilen mit je drei Einträgen ("X", "O" oder " "). Die Funktion gibt "X" oder "O" zurück, wenn jemand drei in einer Reihe, Spalte oder Diagonale hat – sonst None.

def gewinner(feld):
    pass


feld = [
    ["X", "O", " "],
    ["X", "O", " "],
    ["X", " ", "O"],
]
print(gewinner(feld))

Ohne Hinweise gelöst gibt es einen ⭐ auf deiner Fortschrittsseite.

Lösung anzeigen

Versuch es erst selbst – aus Fehlern lernt man am meisten. Hier ist eine mögliche Lösung:

def gewinner(feld):
    linien = []
    for i in range(3):
        linien.append(feld[i])                              # Zeile
        linien.append([feld[0][i], feld[1][i], feld[2][i]])  # Spalte
    linien.append([feld[0][0], feld[1][1], feld[2][2]])      # Diagonale
    linien.append([feld[0][2], feld[1][1], feld[2][0]])      # Gegendiagonale
    for linie in linien:
        if linie[0] != " " and linie[0] == linie[1] == linie[2]:
            return linie[0]
    return None


feld = [
    ["X", "O", " "],
    ["X", "O", " "],
    ["X", " ", "O"],
]
print(gewinner(feld))