Aufgaben

Aufgabe: Interaktiven Spieler implementieren

Erweitern Sie die Klassendefinitionen um eine Unterklasse Human der Klasse Player, die es erlaubt, den auszuwählenden Zug im Terminal einzugeben. Lesen Sie vom Benutzer eine Zahl zwischen eins und der Anzahl gültiger Züge ein und verwenden Sie diese (damit der definierte Spieler für beliebige Spiele verwendet werden kann) als Position im Array gültiger Züge: Bei Eingabe einer 1 soll also der erste gültige Zug zurückgegeben werden, bei einer 2 der zweite und so weiter. Fragen Sie dabei so lange Eingaben ab, bis eine gültige Position eingegeben wurde.

Gehen Sie davon aus, dass durch die Anzeige des Spieles (mit Hilfe von dessen __str__-Methode) klar wird, welche Zahl welchem Zug entspricht. Sie brauchen die gültigen Züge also nicht gesondert auf dem Bildschirm auszugeben.

Nach der Definition Ihrer Klasse, sollten Sie wie folgt gegen einen Zufallsspieler im Nim-Spiel antreten können.

>>> alice = Human("Alice")
>>> bob = RandomPlayer("Bob")
>>> SimpleNim(alice,bob,21).play()
21      matches, Alice's turn
Your choice: 2
19      matches, Bob's turn
17      matches, Alice's turn
Your choice: 1
16      matches, Bob's turn
15      matches, Alice's turn
Your choice: 2
13      matches, Bob's turn
11      matches, Alice's turn
Your choice: 1
10      matches, Bob's turn
9       matches, Alice's turn
Your choice: 2
7       matches, Bob's turn
4       matches, Alice's turn
Your choice: 1
3       matches, Bob's turn
2       matches, Alice's turn
Your choice: 1
1       matches, Bob's turn
0       matches, Alice won

Aufgabe: Verallgemeinertes Nim-Spiel implementieren

In der verallgemeinerten Variante des Nim-Spiels wird mit mehreren Haufen von Streichhölzern gespielt. Ein Zug besteht darin, beliebig viele Streichhölzer (mindestens einen, höchstens alle) aus einem der Haufen heraus zu nehmen. Verloren hat, wer das letzte Streichholz nehmen muss.

Implementieren Sie dieses Spiel in einer Unterklasse Nim der Klasse Game. Überschreiben Sie dazu die Methoden __init__, __str__, has_ended, make_move, winner und valid_moves mit geeigneten Implementierungen. Die Ausgabe der Streichholzhaufen kann so aussehen wie im folgenden Beispiel gezeigt.

Hinweis: Die Methode join auf Zeichenketten ist hilfreich mehrere Zeichenketten aneinander zu hängen. Zum Beispiel liefert "+".join(["a","b","c"]) den Wert "a+b+c" zurück.

>>> alice = Human("Alice")
>>> bob = RandomPlayer("Bob")
>>> Nim(alice,bob,[1,3,5]).play()
Alice's turn
1
2 3 4
5 6 7 8 9
Your choice: 7
Bob's turn
1
2 3 4
5 6
Alice's turn
1
2 3
4 5
Your choice: 1
Bob's turn

1 2
3 4
Alice's turn

1
2 3
Your choice: 3
Bob's turn

1

Alice won

Jeder Haufen wird in einer Zeile ausgegeben. Jede Zeile enthält so viele Zahlen, wie Streichölzer im entsprechenden Haufen liegen. Die Zahlen sind fortlaufend nummeriert. Bei Auswahl eines Zuges werden aus dem entsprechenden Haufen alle Streichhölzer bis zur eingegebenen Zahl entfernt.

Bonusaufgabe: Tic-Tac-Toe implementieren

Implementieren Sie das Spiel Tic Tac Toe als Unterklasse der Klasse Game. Ein Spiel zwischen Mensch und Zufallsspieler kann zum Beispiel so ausshehen:

irb> xavier = Human("Xavier")
irb> olga = RandomPlayer("Olga")
irb> TicTacToe(xavier,olga).play()
Xavier's turn
 1 2 3
 4 5 6
 7 8 9
Your choice: 1
Olga's turn
 X 1 2
 3 4 5
 6 7 8
Xavier's turn
 X O 1
 2 3 4
 5 6 7
Your choice: 3
Olga's turn
 X O 1
 2 X 3
 4 5 6
Xavier's turn
 X O 1
 2 X 3
 4 O 5
Your choice: 5
Xavier wins
 X O 1
 2 X 3
 4 O X

Belegte Felder werden hier mit dem Anfangsbuchstaben des entsprechenden Spielers gekennzeichnet; freie Felder mit einer Zahl, die als Zug eingegeben werden kann.

Hinweis: Der Python-Operator in ist hilfreich, um zu testen, ob ein Element in einem Array enthalten ist. Zum Beispiel hat der Ausdruck "a" in ["a","b","c"] den Wert True.