I am trying to build a simple Tic-Tac-Toe game in python, to check for a win I am using a nested loop to search for a match in a nested lists. For some reason my code will only search the first nested list and not the rest of them as I expected it to.
board = [ 'O', 'X', ' ', 'O', ' ', 'X', 'O', 'X', 'X' ]
wins = [[0,1,2],[3,4,5],[6,7,8],[0,3,6],[1,4,7],[2,5,8],[0,4,8],[2,4,6]]
def checkWin(player):
win = False
for test in wins:
print (test)
count = 0
for squares in test:
if board[squares] == player:
count = count + 1
if count == 3:
win = True
return win
if __name__ == '__main__':
print ("\nChecking board for X win ...\n")
if checkWin("X"):
print ("Game over, X wins!")
print ("\nChecking board for O win ...\n")
if checkWin("O"):
print ("Game over, O wins")
Based on the board provided a win for O is expected instead, this is the output I get:
Checking board for X win ...
[0, 1, 2]
Checking board for O win ...
[0, 1, 2]
Does anyone know why this happens?
You return from the first nested list test, regardless of wether those three squares matched. Instead, only return if win
is true:
def checkWin(player):
win = False
for test in wins:
count = 0
for squares in test:
if board[squares] == player:
count = count + 1
if count == 3:
win = True
if win:
return True
return False
If win
is false, the above continues to the next nested list for the next test.
Better still, just return when count
is set to 3
, since you know you have found a match at that stage:
def checkWin(player):
for test in wins:
count = 0
for squares in test:
if board[squares] == player:
count = count + 1
if count == 3:
return True
return False
Instead of counting, you could use the all()
function:
def checkWin(player):
for test in wins:
if all(board[square] == player for square in test):
return True
return False
all()
returns False
early, as soon as one of the tests in the generator expression fails.
And the ultimate version adds any()
to complete the test in one line:
def checkWin(player):
return any(all(board[square] == player for square in test)
for test in wins)
Demo:
>>> board = [ 'O', 'X', ' ', 'O', ' ', 'X', 'O', 'X', 'X' ]
>>> wins = [[0,1,2],[3,4,5],[6,7,8],[0,3,6],[1,4,7],[2,5,8],[0,4,8],[2,4,6]]
>>> def checkWin(player):
... return any(all(board[square] == player for square in test)
... for test in wins)
...
>>> checkWin('X')
False
>>> checkWin('O')
True