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 im oberen Kanal durch Bewegung mit der Maus über die gewählte Spalte setzen und per Mausklick herunterlassen..Wenn die Spalte nicht bereits voll ist, besetzt der Spielstein 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.

 

 

# FourInARow.py

from gamegrid import *

#------------- 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
        self.setActEnabled(False) # do not start act() yet
 
    def act(self):
        global activeToken, isFalling, isFinished
        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 check4Win(self.getLocation()):
                if self.player == 0:
                    won = "Yellow"
                else:
                    won = "Red"    
                setStatusText("Game Over, player " + won + " won!")
                getBg().drawText("Game Over", Point(10, 55))         
                isFinished = True
            else:
                self.player = (self.player + 1) % 2 
                activeToken = Token(self.player)
                addActor(activeToken, Location(6, 0), Location.SOUTH)
                activeToken.setActEnabled(False)
            isFalling = False          

def onMousePressed(e):
    global isFalling
    isFalling = True
    activeToken.setActEnabled(True) # start act()
    
def onMouseMoved(e):
    if isFalling:
        return
    loc = toLocationInGrid(e.getX(), e.getY())
    if not isFinished: 
        activeToken.setX(loc.x)
    refresh() 
    
def getPlayerOfTokenAt(x, y):
    loc = Location(x, y)
    if getOneActorAt(loc) == None:
        return -1
    else:
        return getOneActorAt(loc).getIdVisible()

#for checking nrOfTokens (win situation: nrOfTokens = 4)
def checkDiagonally1(col, row, nrOfTokens):
    for j in range(nrOfTokens):
        adjacentSameTokens = 0
        for i in range(nrOfTokens):
            if (col + i - j) >= 0 and (col + i - j) < 7 and (row + i - j) >= 1 \
               and (row + i - j) < 7 \
               and getPlayerOfTokenAt(col + i - j, row + i - j) == getPlayerOfTokenAt(col, row):
                adjacentSameTokens = adjacentSameTokens + 1
        if adjacentSameTokens >= nrOfTokens:
            return True
    return False

def checkDiagonally2(col, row, nrOfTokens):
    for j in range(nrOfTokens):
        adjacentSameTokens = 0
        for i in range(nrOfTokens):
            if (col - i + j) >= 0 and (col - i + j) < 7 \
               and (row + i - j) >= 1 and (row + i - j) < 7 \
               and getPlayerOfTokenAt(col - i + j, row + i - j) == getPlayerOfTokenAt(col, row):
                 adjacentSameTokens = adjacentSameTokens + 1
        if adjacentSameTokens >= nrOfTokens:
            return True
    return False

def checkHorizontally(col, row, nrOfTokens):
    adjacentSameTokens = 1
    i = 1
    while col - i >= 0 and getPlayerOfTokenAt(col - i, row) == getPlayerOfTokenAt(col, row):
        adjacentSameTokens = adjacentSameTokens + 1
        i = i + 1
    i = 1
    while col + i < 7 and getPlayerOfTokenAt(col + i, row) == getPlayerOfTokenAt(col, row):
        adjacentSameTokens = adjacentSameTokens + 1
        i = i + 1
    return adjacentSameTokens >= nrOfTokens

def checkVertically(col, row, nrOfTokens):
    adjacentSameTokens = 1
    i = 1
    while row + i < 7 and getPlayerOfTokenAt(col, row + i) == getPlayerOfTokenAt(col, row):
       adjacentSameTokens = adjacentSameTokens + 1
       i = i + 1
    return adjacentSameTokens >= nrOfTokens

#return true, if four are connected through that token
def check4Win(loc):
    col = loc.x
    row = loc.y
    return (checkVertically(col, row, 4) 
      or checkHorizontally(col, row, 4)
      or checkDiagonally1(col, row, 4)
      or checkDiagonally2(col, row, 4))

# ---------------- main ----------------------           
makeGameGrid(7, 7, 70, None, "sprites/connectbg.png", False,
     mousePressed = onMousePressed,
     mouseMoved = onMouseMoved)
setBgColor(makeColor("white"))
isFalling = False
activeToken =  Token(0)
isFinished = False
addActor(activeToken, Location(0, 0), Location.SOUTH)
setSimulationPeriod(30)
addStatusBar(30)
setStatusText("Move mouse to a column and click to set the token.")
getBg().setFont(Font("SansSerif", Font.BOLD, 48))
getBg().setPaintColor(Color.red)
show()
doRun()
Programmcode markieren (Ctrl+C kopieren, Ctrl+V einfügen)

 

Erklärungen zum Programmcode:

class Token()): ein Spielstein wird durch die Klasse Token() modelliert. Die Spritebilder token_0.png und token_1.png stellen die gelben und roten Steine dar
check4Win(loc) gibt True zurück, falls einer der Checks (horizontal, vertikal und beide Diagonalen) positiv ausfällt
onMouseMoved(): der aktive Spielstein wird an die Position des Mauszeigers versetzt
onMousePressed(): die Methode act() der Klasse Token wird enabled. Der Spielstein bewegt sich auf den untersten freien Platz in der Spalte