TigerJython xx
für Gymnasien

Online Four-in-a-Row (4 gewinnt )


Four-in-a-Row ist ein Zweipersonen-Strategiespiel. Das Spielbrett besteht aus sieben Spalten (senkrecht) und sechs Reihen (waagrecht). Die Spieler positionieren abwechselnd ihre Spielsteine, indem sie den Spielstein mit Mausklick im oberen Kanal über die gewählte Spalte setzen. Der Spielstein bewegt nach unten und besetzt den untersten freien Platz der Spalte. Gewinner ist der Spieler, der es als Erster schafft, vier seiner Spielsteine waagerecht, senkrecht oder diagonal in eine Linie zu bringen. Das Spiel endet unentschieden, wenn das Spielbrett komplett gefüllt ist, ohne dass ein Spieler eine Viererlinie gebildet hat.

 

  Server
Client

Einige Funktionen und die Klasse Token() werden sowohl im Server- als auch im Clientprogramm benötigt. Diese Programmteile werden in der Datei fourlib.py gespeichert.

Server (wird zuerst gestartet):

# TcpFourServer.py

from gamegrid import *
from tcpcom import TCPServer
import fourlib                                                                    

def onMousePressed(e):
    global isMyMove, location
    if not isMyMove or fourlib.isOver:
          return
    location = toLocationInGrid(e.getX(), e.getY())
    token = fourlib.Token(1)
    addActor(token, location, Location.SOUTH)   
    server.sendMessage(str(location.x)) # send location
    isMyMove = False
    setStatusText("Wait!")    

def onNotifyExit():
    server.terminate()
    dispose()
    
def onStateChanged(state, msg):
    global isMyMove, location
    if state == TCPServer.PORT_IN_USE:
        setStatusText("TCP port occupied. Restart IDE.")
    if state == TCPServer.LISTENING:
        setStatusText("Waiting for a partner to play")        
    if state == TCPServer.CONNECTED:
        setStatusText("Client connected. Wait for partner's move!")
    elif state == TCPServer.MESSAGE:        
        x = int(msg[0])        
        location = Location(x, 0)            
        token = fourlib.Token(0)
        addActor(token, location, Location.SOUTH)     
        isMyMove = True
        setStatusText("Make your move!")
    
makeGameGrid(7, 7, 70, None, "sprites/connectbg.png", False,
    mousePressed = onMousePressed, notifyExit = onNotifyExit)
setBgColor(makeColor("white"))
addStatusBar(30)
isMyMove = False 
show()
setSimulationPeriod(30)
doRun()
port = 5000
server = TCPServer(port, stateChanged = onStateChanged)
Programmcode markieren (Ctrl+C kopieren, Ctrl+V einfügen)

------------------------------------------------------------------------------------------------------------------------------
Client:

# TcpFourClient.py

from gamegrid import *
from tcpcom import TCPClient
import fourlib                                                                            
       
def onMousePressed(e):
    global isMyMove, location
    if not isMyMove or fourlib.isOver:
        return
    location = toLocationInGrid(e.getX(), e.getY())
    token = fourlib.Token(0)
    addActor(token, location, Location.SOUTH)  

    client.sendMessage(str(location.x)) 
    setStatusText("Wait!")        
           
def onNotifyExit():
    client.disconnect()
    dispose()
   
def onStateChanged(state, msg):
    global isMyMove, location
    if state == TCPClient.CONNECTED:
        setStatusText("Connection established. You play!")
        isMyMove = True
    elif state == TCPClient.CONNECTION_FAILED:
        setStatusText("Connection failed")
    elif state == TCPClient.DISCONNECTED:
        setStatusText("Server died")
        isMyMove = False
    elif state == TCPClient.MESSAGE:        
        x = int(msg[0])           
        location = Location(x, 0)           
        token = fourlib.Token(1)
        addActor(token, location, Location.SOUTH)
        isMyMove = True
        setStatusText("Make your move!")

makeGameGrid(7, 7, 70, None, "sprites/connectbg.png", False,
     mousePressed = onMousePressed, notifyExit = onNotifyExit)
setBgColor(makeColor("white"))
isMyMove = False 
addStatusBar(30)
show()
setSimulationPeriod(30)
doRun()
host = "localhost"
port = 5000
client = TCPClient(host, port, stateChanged = onStateChanged)
client.connect()
Programmcode markieren (Ctrl+C kopieren, Ctrl+V einfügen)

------------------------------------------------------------------------------------------------------------------------------------
Import-Datei:

# fourlib.py

from gamegrid import *

isOver = False

#----------class Token -------------------------------
class Token(Actor):
    def __init__(self, player):
        Actor.__init__(self, "sprites/token.png", 2)
        self.player = player
        self.show(player)
        self.nb = 0

    def act(self):
        global isOver
        nextLoc = Location(self.getX(), self.getY() + 1)
        if (getOneActorAt(nextLoc) == None and self.isMoveValid()):
            if self.nb == 6:
                self.nb = 0
                self.setLocationOffset(Point(0, 0))
                self.move()
            else:
                self.setLocationOffset(Point(0, 10 * self.nb))
            self.nb = self.nb + 1 
        else:  # arrived
            self.setActEnabled(False)  # old token will stay where it is
            if checkOver(self.getLocation()):
                if self.player == 0:
                    won = "Yellow"
                else:
                    won = "Red"    
                setStatusText("Game Over, player " + won + " won!")             
                isOver = True   

#----------check Game over-------------------------------------
def getId(x, y):
    loc = Location(x, y)
    if getOneActorAt(loc) == None:
        return -1
    else:
        return getOneActorAt(loc).getIdVisible()

#check for four
def checkDiagonal(col, row):
    for j in range(4):
        nb = 0
        for i in range(4):
            if (col + i - j) >= 0 and (col + i - j) < 7 and (row + i - j) >= 1 \
               and (row + i - j) < 7 \
               and getId(col + i - j, row + i - j) == getId(col, row):
                nb = nb + 1
        if nb >= 4:
            return True
    return False

def checkDiagonal2(col, row):
    for j in range(4):
        nb = 0
        for i in range(4):
            if (col - i + j) >= 0 and (col - i + j) < 7 \
               and (row + i - j) >= 1 and (row + i - j) < 7 \
               and getId(col - i + j, row + i - j) == getId(col, row):
                 nb = nb + 1
        if nb >= 4:
            return True
    return False

def checkHorizontal(col, row):
    nb = 1
    i = 1
    while col - i >= 0 and getId(col - i, row) == getId(col, row):
        nb = nb + 1
        i += 1
    i = 1
    while col + i < 7 and getId(col + i, row) == getId(col, row):
        nb = nb + 1
        i += 1
    return nb >= 4

def checkVertical(col, row):
    nb = 1
    i = 1
    while row + i < 7 and getId(col, row + i) == getId(col, row):
       nb = nb + 1
       i += 1
    return nb >= 4

#return true, if four in a row
def checkOver(loc):
    col = loc.x
    row = loc.y
    return (checkVertical(col, row) 
      or checkHorizontal(col, row)
      or checkDiagonal(col, row)
      or checkDiagonal2(col, row)) 
Programmcode markieren (Ctrl+C kopieren, Ctrl+V einfügen)

 

Erklärungen zum Programmcode:

class Token(): Die Spielsteine sind Objekte der Klasse Token(). Die Klasse verwendet zwei Spritebilder token_0.png für die gelben und token_1.png für die roten Steine. In der Methode act() wird die Bewegung der Spielsteine festgelegt
checkOver(loc) gibt True zurück, falls einer der Checks (horizontal, vertikal und beide Diagonalen) positiv ausfällt