Reputation: 1271
I am working on a tic tack toe game in python (to improve my python skills) and am stuck on the following problem: I have a list of lists like below which determine whether or not a player has won depending on if all values either, vertically, horizontally, or diagonally have the same value.
win_horizontal = [[board[0], board[1], board[2]], [board[3], board[4], board[5]], [board[6], board[7], board[8]]]
win_vertical = [[board[0], board[3], board[6]], [board[1], board[4], board[7]], [board[2], board[5], board[8]]]
win_diagonal = [[board[0], board[4], board[8]], [board[2], board[4], board[6]]]
So at present, I have the following logic:
result = False;
result = all(elem == mark for elem in win_horizontal[1])
if result :
print("All Elements in List are Equal")
else:
print("All Elements in List are Not Equal")
This works as I am only checking one list within the list. However, I am not sure how to check against all of the list of lists to determine whether or not the player has won diagonally, horizontally, or vertically. I want to be able to check against all of the list of lists.
I tried the following
def win_check(board, mark):
win_horizontal = [[board[0], board[1], board[2]], [board[3], board[4], board[5]], [board[6], board[7], board[8]]]
win_vertical = [[board[0], board[3], board[6]], [board[1], board[4], board[7]], [board[2], board[5], board[8]]]
win_diagonal = [[board[0], board[4], board[8]], [board[2], board[4], board[6]]]
winner = [win_horizontal, win_vertical, win_diagonal]
result = False;
result = all(elem == mark for elem in any(winner))
if result :
print("All Elements in List are Equal")
else:
print("All Elements in List are Not Equal")
But I just get the following error TypeError: 'bool' object is not iterable
which I assume is being raised from any(winner))
What is the best way to check for the winning condition?
Upvotes: 1
Views: 125
Reputation: 166
from typing import Optional, Any
TEAM_A = True
TEAM_B = False
class Board:
# Calculated victory patterns
VICTORY_CELLS = [
[0,1,2], [3,4,5], [6,7,8], # horizontal
[0,3,6], [1,4,7], [2,5,8], # vertical
[0,4,8], [2,4,6], # diagonal
]
def __init__(self):
self._vector: list[Optional[Any]] = [None for _ in range(9)]
def check_winner(self, marker) -> bool:
# Get set of indexes where player has put his marker
player_cells = {i for i, v in enumerate(self._vector) if v == marker}
# For every victory pattern, if it is a subset of players markers, return True
return any(player_cells.issuperset(victory) for victory in self.VICTORY_CELLS)
def __setitem__(self, key, value):
if isinstance(key, int) and 0 <= key <= 8:
self._vector[key] = value
board = Board()
board[0] = TEAM_A
board[4] = TEAM_A
print('Team A victory: ', board.check_winner(TEAM_A))
print('Team B victory: ', board.check_winner(TEAM_B))
board[8] = TEAM_A
print('Team A victory: ', board.check_winner(TEAM_A))
print('Team B victory: ', board.check_winner(TEAM_B))
Result will be:
Team A victory: False
Team B victory: False
Team A victory: True
Team B victory: False
You should just make sure game won't continue after one's victory.
Upvotes: 0
Reputation: 42143
It is probably simpler to check for the player's winning pattern rather than equality of the 3 board positions.
player = 'X' # last played
winPattern = [player]*3
boardPatterns = win_horizontal + win_vertical + win_diagonal
if winPattern in boardPatterns:
print(player,'wins!')
As a side note, you don't have to separate the 3 axis directions in 3 variables, you could build a single list of patterns to work from:
positions = [(0,1,2),(3,4,5),(6,7,8),(0,3,6),(1,4,7),(2,5,8),(0,4,8),(2,4,6)]
boardPatterns = [[board[p] for p in axis] for axis in positions]
Upvotes: 1
Reputation: 54148
You need an any
between horizontal, vertical, diagonal, and a all
on each
result = any(
all(elem == mark for elem in win)
for win in winner
)
Upvotes: 3