TigerJython4Kids
HomeTurtlegrafikRobotikDatenbanken
tictactoe

ARBEITSBLATT 4: GAMEN MIT TIC-TAC-TOE

 

 

SPIELBESCHREIBUNG

 

Zwei Spieler können nacheinander in einem 3x3 Gitter in leere Zellen ihre Marke setzen, z.B. Kringel und  Kreuze oder rote und grüne Steine. Wer zuerst 3 Marken auf einer Zeile, Spalte oder Diagonale setzten kann, hat gewonnen.

Auf der Oxocard sind die Steine als rote oder grüne Quadrate sichtbar. Mit 4 Cursortasten kann der Spieler, der am Zug ist, einen hell-farbigen Cursor auf eine Zelle verschieben und mit der OK-Taste dort seinen Stein setzen.

 

 

 

TEILAUFGABE 1: DEN SPIELZUSTAND BESCHREIBEN

 

Du kannst das Display wie ein Spielbrett (Game Board) auffassen. In jedem Moment des Spiels befindet sich dieses in einem bestimmten Zustand. Es ist sehr wichtig, dass du den Zustand in einer angepassten Datenstruktur beschreibst. Du verwendest hier eine Liste state mit 9 Elementen, wobei der Index zeilenweise den Zellen entspricht. Du legst fest, dass der Wert -1 eine leere Zelle, eine 0 eine Marke des Spielers 0 und eine 1 eine Marke des Spielers 1 angibt. Beispielsweise wird der oben gezeichnete Spielzustand beschrieben durch:

state = [0, 0, 1, -1, 1, -1, -1, 1, -1]

Der Cursor befindet sich in der Zelle mit dem Index 6. Diese Information gehört ebenfalls zum Spielzustand, sowie auch, dass gerade Spieler 0 (mit den roten Steinen) am Zug ist, da der Cursor hellrot erscheint.

Für die Bewegung des Cursors eignet sich der Zellenindex schlecht. Besser verwendest du für den Cursorzustand eine Zellenangabe location mit zwei Werten im Bereich 0 bis 3. (Diese Werte entsprechen noch nicht direkt seiner Lage auf dem Display.) Es ist wichtig, dass du gleich zwei Transformationsfunktionen toLocation(index) und toIndex(location) schreibst, damit du von der lästigen Umrechnerei zwischen dem Index und der Location ein für alle Mal befreit bist. (Man pflegt solche Funktionen mit to.. einzuleiten.)

Zuerst  willst du ein paar fest gewählte Spielzustände darstellen. Du brauchst in folgender Vorlage nur noch in der Funktion drawBoard() ein paar Zeilen einzusetzen.

Programm:

from oxocardext import *

def toLocation(index):
    locX = index % 3
    locY = index // 3
    return (locX, locY)

def toIndex(location):
    return 3 * location[1] + location[0]

def drawBoard():
    for index in range(9):
        x, y = toPoint(index)
        # todo
  
enableRepaint(False)
state = [0, 0, 0, 0, 0, 0, 0, 0, 0]
drawBoard()
repaint()
sleep(3)    
state = [1, 1, 1, 1, 1, 1, 1, 1, 1]
drawBoard()
repaint()
sleep(3)    
state = [1, -1, 0, 0, 1, -1, 0, -1, 1]
drawBoard()
repaint()
► In Zwischenablage kopieren

Damit immer gleich das ganze Spielbrett auf einmal neu erscheint, verwendest du enableRepaint(False).

 

 

TEILAUFGABE 2: CURSORBEWEGUNG EINBAUEN

 

Als nächstens behandelst du die tastengesteueten Cursorbewegungen. Die aktuelle Lage des Cursors speicherst du wie eine Location in einer Liste, die zuerst auf [0, 0] initialisiert ist. In einer Endlosschleife des Hauptprogramms überprüfst du, ob einer der Buttons gedrückt wurde und veränderst die  Cursorlocation entsprechend. Für die Darstellung auf dem Display schreibst du am besten eine Funktion drawCursor(), die im folgenden Programmskelett bereits ausprogrammiert ist.

Baue jetzt das Skelett in dein Programm ein und ergänze die fehlenden Blöcke. Verhindere auch, dass man den Cursor über den Rand des Displays hinausschieben kann.

def drawCursor():
    if player == 0:
        color = (255, 0, 0)
    else:
        color = (0, 255, 0)
    dot(3 * cursor[0], 3 * cursor[1], color)

btnUp = Button(BUTTON_L2)
btnDown = Button(BUTTON_L3)
btnLeft = Button(BUTTON_R3)
btnRight = Button(BUTTON_R2)
  
enableRepaint(False)
state = [1, -1, 0, 0, 1, -1, 0, -1, 1]
cursor = [0, 0]  # x, y 
player = 0

while True:
    if btnUp.wasPressed():
        ...
    elif btnDown.wasPressed():
        ...
    elif btnLeft.wasPressed():
        ...
    elif btnRight.wasPressed():
        ...
    drawBoard()
    drawCursor()
    repaint()
    sleep(0.1)    

In der Endlosschleife wird das Display ständig neu gezeichnet, auch wenn sich nichts ändert. Damit dies nicht allzu häufig geschieht, ist ein sleep(0.1s) eingebaut. Man könnte die Programmlogik auch so ändern, dass nur dann das Display neu gezeichnet wird, falls sich etwas ändert. Trotzdem müsste man in der Schleife mit einem sleep verhindern, dass sie leer durchlaufen wird, weil sonst unnötig viel Rechenzeit vergeudet würde.

 

 

TEILAUFGABE 3: MIT OK-BUTTON DIE WAHL BESTÄTIGEN

 

 

Nachdem ein Spieler den Cursor auf eine Zelle gesetzt hat, soll er mit Klicken auf einen OK- Button die Wahl bestätigen. Falls sich der Cursor in einer leeren Zelle befindet, wird der Stein gesetzt und der Spieler gewechselt, d.h. die Variable player neu zugewiesen. Mit dieser Ergänzung hast du das Spiel bereits fertiggestellt . Mit dieser Ergänzung hast du das Spiel bereits fertiggestellt und du kannst jemanden zum Spielen herausfordern. Es ist deiner Fantasie und deinem Erfindergeist überlassen, das Spiel. nach deinen eigenen Ideen etwas individueller zu gestalten (andere Farben, usw.).

 

 

 

ERWEITERUNG 1*: TESTEN, OB DAS SPIEL BEENDET IST

 

Baue eine Funktion patternAligned(state) ein, die True zurückgibt, falls im übergebenen Spielzustand state drei Steine der einen oder anderen Farbe auf einer Zeile, Spalte oder Dialogonale liegen. Schreibe eine Erfolgsmeldung aus, falls ein Spieler diesen Zustand erreicht und beende das Spiel. Schreibe auch eine Meldung aus, falls das Spiel bei vollem Spielfeld unentschieden ausgeht.

 

 

ERWEITERUNG 2*ONLINE-GAME MIT 2 OXOCARDs

 

(Für Kommunikationsprofis) Verwende die Datenkommunikation über MQTT, damit zwei Spieler auf verschiedenen Oxocards miteinander auch weit entfernt voneinander spielen können.

 

 

ERWEITERUNG 3*GEGEN COMPUTER SPIELEN

 

(Für Strategieprofis). Baue eine Gewinnstrategie ein, damit du mit dem Computer als Spielpartner spielen kannst, d.h. nach deinem Stein  setzt der Computer seinen Stein gemäss dieser Strategie, bis einer der beiden das Spiel gewonnen hat oder das Spielfeld voll ist.