Jakemmarsh
Jakemmarsh

Reputation: 4671

Python Connect Four game win function

I have most of my Python version of Connect Four coded, except for the win function and the gravity. Below is the code for determining if the game has been won yet.. It doesn't function, currently the only way the game ends is if all the spots are taken up. Any ideas?

winners = [ [1,2,3,4],[2,3,4,5],[3,4,5,6],[4,5,6,7],[8,9,10,11],[9,10,11,12],[10,11,12,13],[11,12,13,14],
                    [15,16,17,18],[16,17,18,19],[17,18,19,20],[18,19,20,21],[22,23,24,25],[23,24,25,26],[24,25,26,27],
                    [25,26,27,28],[29,30,31,32],[30,31,32,33],[31,32,33,34],[32,33,34,35],[36,37,38,39],[37,38,39,40],
                    [38,39,40,41],[39,40,41,42],[1,8,15,22],[8,15,22,29],[15,22,29,36],[2,9,16,23],[9,16,23,30],[16,23,30,37],
                    [3,10,17,24],[10,17,24,31],[17,23,31,38],[4,11,18,25],[11,18,25,32],[18,24,32,39],[5,12,19,26],[12,19,26,33],
                    [19,25,33,40],[6,13,20,27],[13,20,27,34],[20,28,34,41],[7,14,21,28],[14,21,28,35],[21,28,35,42],[1,9,17,25],
                    [9,17,25,33],[17,25,33,41],[8,16,24,32],[16,24,32,40],[15,23,31,39],[2,10,18,26],[10,18,26,34],[18,26,34,42],
                    [3,11,19,27],[11,19,27,35],[4,12,20,28] ]

    def makeMove(self):
        self.Player = self.game.Player

        if self.game.Player == 'Black':
            self.b.config(image=self.Black, command=self.invalidMove)
            num = self.num
            self.game.moves['Black'].append(num)
            self.game.free.remove(num)
            w = self.won(self.game.Player)
            if self.game.moves['Black'] in winners:
                self.game.turninfo.config(text=self.game.Player+' WON!')
            elif self.game.free == [ ]:
                self.game.turninfo.config(text='Game is a draw!')
            else:
                self.game.Player = 'Red'
                self.game.turninfo.config(text=self.game.Player+"'s Turn")
        elif self.game.Player == 'Red':
            self.b.config(image=self.Red, command=self.invalidMove)
            num = self.num
            self.game.moves['Red'].append(num)
            self.game.free.remove(num)
            w = self.won(self.game.Player)
            if contains(self.game.moves['Red'],winners):
                self.game.turninfo.config(text=Player+' WON!')
                for c in self.game.cells:
                    c.freeze()
            elif self.game.free == [ ]:
                self.game.turninfo.config(text='Game is a draw!')
                for c in self.game.cells:
                    c.freeze()
            else:
                self.game.Player = 'Black'
                self.game.turninfo.config(text=self.game.Player+"'s Turn")

Upvotes: 0

Views: 1817

Answers (1)

Andrew Clark
Andrew Clark

Reputation: 208505

I think your issue is that you are checking to see if a players moves match one of the win conditions exactly. This is possible but probably won't happen that often, for example a player might make the moves [2, 3, 1, 4] which should count as a win, but [2, 3, 1, 4] is not in winners so you will not get a match. Also, if it ever took a player more than four moves you would never get a winner for the same reason (since [6, 1, 2, 3, 4] wouldn't be found in winners either).

What you actually want to find out is if for any of the win conditions, all of the moves of the win condition were made by a player. This can be expressed like this:

for winner in winners:
    won = True
    for move in winner:
        if move not in self.game.moves['Black']:
            won = False
    if won:
        # game ending logic
        break

This can be shortened considerably to the following (but it might be harder to follow):

if any(all(m in self.game.moves['Black'] for m in w) for w in winners)):
    # game ending logic

Upvotes: 1

Related Questions