Auf einem 8×8-Brett legen zwei Spieler abwechslungsweise gelbe und rote Spielsteine. Zu Beginn des Spiels sind bereits je zwei gelbe und rote Steine in der Mitte des Spielbretts gelegt. Die weiteren Spielsteine können per Mausklick in leere Zellen gelegt werden, bei welchen mindestens eine der benachbarten Zellen oben, unten, links oder rechts belegt ist. |
|
Wird ein Stein gelegt, so werden alle gegnerischen Steine, die sich in Reihen oder Diagonalen zwischen dem neuen und bereits gelegten Steinen der eigenen Farbe befinden, durch Steine der eigenen Farbe ersetzt. Das Ziel des Spiels ist es, am Ende möglichst viele eigene Steine auf dem Brett zu haben. Das Spiel ist fertig, wenn alle Zellen belegt sind.
Player 0 |
Player 1 |
Die beiden Spieler verwenden das gleiche Topic /swissgame/reversi und müssen die Programmzeile player = 0 bzw. player = 1 ergänzen. Der Player 0 beginnt. Da hier die Überprüfung der Spielsituation nach jedem Zug etwas anspruchsvoller ist, ist es sinnvoll die Initialisierung und die Check-Funktionen in einer separaten Datei reversilib.py zu speichern. Im Hauptprogramm wird diese Datei mit import reversilib importiert und ihren Funktionen mit vorangestellten reversilib. aufgerufen.
So wie in den vorhergehenden Beispielen werden jeweils die x- und y-Koordinaten des Mausklicks übermittelt. Die Überprüfung des Spielsituation und das Kehren der Spielsteine erfolgt bei jedem Spieler autonom.
# Reversi.py from gamegrid import * from mqttclient import GameClient import reversilib player = x # set player = 0 or player = 1 myTopic = "/swissgame/reversi" def onMousePressed(e): global isMyMove, location if not isMyMove or isOver: return location = toLocationInGrid(e.getX(), e.getY()) if getOneActorAt(location) == None and reversilib.hasNeighbours(location): stone = Actor("sprites/token.png", 2) addActor(stone, location) stone.show(player) reversilib.checkStones(player, location) refresh() client.sendMessage(str(location.x) + str(location.y)) # send location isMyMove = False setStatusText("Wait!") if len(getOccupiedLocations()) == 64: reversilib.endOfGame() client.sendMessage("end") def onNotifyExit(): client.disconnect() dispose() def onStateChanged(state): global isMyMove if state == "CONNECTING": setStatusText("Connecting to broker...") elif state == "CONNECTED": setStatusText("Connected. Waiting for partner...") elif state == "READY": if player == 0: setStatusText("Make a move!") isMyMove = True else: setStatusText("Wait for partner's move!") elif state == "DISCONNECTED": setStatusText("Partner disconnected!") isMyMove = False def onMessageReceived(msg): global isMyMove if msg == "end": reversilib.endOfGame() else: x = int(msg[0]) y = int(msg[1]) location = Location(x, y) stone = Actor("sprites/token.png", 2) addActor(stone, location) stone.show(partner) reversilib.checkStones(partner, location) refresh() isMyMove = True setStatusText("Make your move!") isMyMove = False isOver = False partner = (player + 1) % 2 makeGameGrid(8, 8, 60, Color.gray, False, mousePressed = onMousePressed, notifyExit = onNotifyExit) addStatusBar(30) reversilib.initGame() show() if player == 0: setTitle("Player with yellow stones") else: setTitle("Player with red stones") host = "m2m.eclipse.org" client = GameClient(onStateChanged, onMessageReceived, myTopic) client.connect(host) |
-----------------------------------------------------------------------------------------------------------------------------------
# reversilib.py from gamegrid import * def initGame(): yellow = Actor("sprites/token.png", 2) yellow2 = Actor("sprites/token.png", 2) red = Actor("sprites/token.png", 2) red2 = Actor("sprites/token.png", 2) addActor(yellow, Location(3, 3)) addActor(yellow2, Location(4, 4)) addActor(red, Location(4, 3)) addActor(red2, Location(3, 4)) yellow.show(0) yellow2.show(0) red.show(1) red2.show(1) #Checks if cell has a neighbour in the north, east, south or west def hasNeighbours(loc): locs = toList(loc.getNeighbourLocations(0.5)) for i in range(4): if getOneActorAt(locs[i]) != None: return True return False # Check for stones in all 8 directions and if they can be turned add list def checkStones(imageID, location): for c in range (0, 360, 45): actors = [] loc = location.getNeighbourLocation(c) a = getOneActorAt(loc) hasSameImageID = False while a != None and not hasSameImageID: if a.getIdVisible() != imageID: actors.append(a) loc = loc.getNeighbourLocation(c) a = getOneActorAt(loc) else: if a.getIdVisible() == imageID: hasSameImageID = True # Turn stones if hasSameImageID: for actor in actors: actor.show(imageID) # endOfGame def endOfGame(): countYellow = 0 countRed = 0 all = getOccupiedLocations() for lc in all: if getOneActorAt(lc).getIdVisible() == 0: countYellow += 1 else: countRed += 1 if len(all) == 64: if countRed > countYellow: setStatusText("Game over. Red wins with score: " + str(countRed) + ":" + str(countYellow)) elif countRed < countYellow: setStatusText("Game over. Yellow wins with score: " + str(countYellow) + ":" + str(countRed)) else: setStatusText("The game ended in a tie") |
Erklärungen zum Programmcode:
reversilib.initGame(): Erzeugt das Spielfeld mit 2 roten und gelben Steinen. Diese Funktion ist in reversilib.py definiert, deswegen muss reversilib. vorangestellt werden | |
locs = toList(loc.getNeighbourLocations(0.5)): Liste der 4 direkt benachbarten Zellen | |
for c in range (0, 360, 45): 8 Richtungen 0, 45, 90, 135,...315 | |
loc = location.getNeighbourLocation(c): Liefert benachbarte Zellen, die in der Richtung c liegen | |
all = getOccupiedLocations(): Liste aller besetzten Zellen |