TigerJython xx
für Gymnasien

Online Reversi


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.

 
 
 
nicht erlaubt
 
erlaubt
 

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)
Programmcode markieren (Ctrl+C kopieren, Ctrl+V einfügen)

-----------------------------------------------------------------------------------------------------------------------------------

# 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")  
Programmcode markieren (Ctrl+C kopieren, Ctrl+V einfügen)

 

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