⭕❌⭕ The Tic Tac Toe Referee (Solution)¶
Scenario:
You're a famous Tic Tac Toe referee, and you've been called in to resolve a dispute between two players. Multiple games have been played but no one can remember exactly how they played out, and checking all the games by hand would take a lot of time.
Exercise:
You've been given the moves for each game, and you need to figure out the winner of each game where 1 represents player 1, 2 represents player 2, and 0 represents an empty space.
In [1]:
Copied!
import numpy as np
# Initialize an array of zeros with the dimensions of your games
num_games = 1000
games = np.zeros((num_games, 3, 3), dtype=int)
# Fill the array with random moves
for game in games:
# Randomly choose your moves
num_your_moves = np.random.randint(1, 5)
your_moves = np.random.choice(9, num_your_moves, replace=False)
np.put(game, your_moves, 1) # Fill your moves into the game grid
# Randomly choose the opponent's moves
num_opponent_moves = np.random.randint(1, 9 - num_your_moves)
opponent_moves = np.random.choice(list(set(range(9)) - set(your_moves)), num_opponent_moves, replace=False)
np.put(game, opponent_moves, 2)
import numpy as np
# Initialize an array of zeros with the dimensions of your games
num_games = 1000
games = np.zeros((num_games, 3, 3), dtype=int)
# Fill the array with random moves
for game in games:
# Randomly choose your moves
num_your_moves = np.random.randint(1, 5)
your_moves = np.random.choice(9, num_your_moves, replace=False)
np.put(game, your_moves, 1) # Fill your moves into the game grid
# Randomly choose the opponent's moves
num_opponent_moves = np.random.randint(1, 9 - num_your_moves)
opponent_moves = np.random.choice(list(set(range(9)) - set(your_moves)), num_opponent_moves, replace=False)
np.put(game, opponent_moves, 2)
Your Tasks:
- Create a function that checks if a player has won a game along the rows.
In [2]:
Copied!
def check_row(row: np.ndarray) -> int:
"""Check if a row is a winning row.
Args:
row (np.ndarray): A row of a tic-tac-toe game. Shape (3,).
Returns:
int: 1 if the row is a winning row for the player 1,
2 if the row is a winning row for the player 2,
0 otherwise.
"""
if np.all(row == 1):
return 1
elif np.all(row == 2):
return 2
else:
return 0
def check_row(row: np.ndarray) -> int:
"""Check if a row is a winning row.
Args:
row (np.ndarray): A row of a tic-tac-toe game. Shape (3,).
Returns:
int: 1 if the row is a winning row for the player 1,
2 if the row is a winning row for the player 2,
0 otherwise.
"""
if np.all(row == 1):
return 1
elif np.all(row == 2):
return 2
else:
return 0
- Create a function that checks if a player has won a game along the rows using the previous function.
In [3]:
Copied!
def check_rows(grid: np.ndarray) -> int:
"""Check if any row is a winning row.
Args:
grid (np.ndarray): A tic-tac-toe game. Shape (3, 3).
Returns:
int: 1 if the row is a winning row for the player 1,
2 if the row is a winning row for the player 2,
0 otherwise.
"""
for row in grid:
result = check_row(row)
if result != 0:
return result
return 0
def check_rows(grid: np.ndarray) -> int:
"""Check if any row is a winning row.
Args:
grid (np.ndarray): A tic-tac-toe game. Shape (3, 3).
Returns:
int: 1 if the row is a winning row for the player 1,
2 if the row is a winning row for the player 2,
0 otherwise.
"""
for row in grid:
result = check_row(row)
if result != 0:
return result
return 0
- Create a function that checks if a player has won a game along the columns.
In [4]:
Copied!
def check_columns(grid: np.ndarray) -> int:
"""Check if any column is a winning column.
Args:
grid (np.ndarray): A tic-tac-toe game. Shape (3, 3).
Returns:
int: 1 if the row is a winning row for the player 1,
2 if the row is a winning row for the player 2,
0 otherwise.
"""
return check_rows(grid.T) # Transpose the grid to check the columns
def check_columns(grid: np.ndarray) -> int:
"""Check if any column is a winning column.
Args:
grid (np.ndarray): A tic-tac-toe game. Shape (3, 3).
Returns:
int: 1 if the row is a winning row for the player 1,
2 if the row is a winning row for the player 2,
0 otherwise.
"""
return check_rows(grid.T) # Transpose the grid to check the columns
- Create a function that checks if a player has won a game along the diagonals.
In [5]:
Copied!
def check_diagonals(grid: np.ndarray) -> int:
"""Check if any diagonal is a winning diagonal.
Args:
grid (np.ndarray): A tic-tac-toe game. Shape (3, 3).
Returns:
int: 1 if the row is a winning row for the player 1,
2 if the row is a winning row for the player 2,
0 otherwise.
"""
diagonal_0 = np.diag(grid)
diagonal_1 = np.diag(np.fliplr(grid))
diagonals = np.array([diagonal_0, diagonal_1], dtype=int) # Combine the diagonals
return check_rows(diagonals)
def check_diagonals(grid: np.ndarray) -> int:
"""Check if any diagonal is a winning diagonal.
Args:
grid (np.ndarray): A tic-tac-toe game. Shape (3, 3).
Returns:
int: 1 if the row is a winning row for the player 1,
2 if the row is a winning row for the player 2,
0 otherwise.
"""
diagonal_0 = np.diag(grid)
diagonal_1 = np.diag(np.fliplr(grid))
diagonals = np.array([diagonal_0, diagonal_1], dtype=int) # Combine the diagonals
return check_rows(diagonals)
- Create a function that checks if a player has won a game using the previous three functions.
In [6]:
Copied!
def check_win(grid: np.ndarray) -> int:
"""Check if any row, column, or diagonal is a winning row, column, or
diagonal.
Args:
grid (np.ndarray): A tic-tac-toe game. Shape (3, 3).
Returns:
int: 1 if a row, column, or diagonal is a winning row, column, or
diagonal for the player 1, 2 if it is a winning row, column, or
diagonal for the player 2, 0 otherwise.
"""
# check rows
result = check_rows(grid)
if result != 0:
return result
# check columns
result = check_columns(grid)
if result != 0:
return result
# check diagonals
result = check_diagonals(grid)
if result != 0:
return result
# no win
return 0
def check_win(grid: np.ndarray) -> int:
"""Check if any row, column, or diagonal is a winning row, column, or
diagonal.
Args:
grid (np.ndarray): A tic-tac-toe game. Shape (3, 3).
Returns:
int: 1 if a row, column, or diagonal is a winning row, column, or
diagonal for the player 1, 2 if it is a winning row, column, or
diagonal for the player 2, 0 otherwise.
"""
# check rows
result = check_rows(grid)
if result != 0:
return result
# check columns
result = check_columns(grid)
if result != 0:
return result
# check diagonals
result = check_diagonals(grid)
if result != 0:
return result
# no win
return 0
- Compute how many games you've won/lost/drawn in the dataset.
In [7]:
Copied!
player_1, player_2, draws = 0, 0, 0
for game in games:
result = check_win(game)
if result == 1:
player_1 += 1
elif result == 2:
player_2 += 1
else:
draws += 1
print(f"Player 1 wins: {player_1}")
print(f"Player 2 wins: {player_2}")
print(f"Draws: {draws}")
player_1, player_2, draws = 0, 0, 0
for game in games:
result = check_win(game)
if result == 1:
player_1 += 1
elif result == 2:
player_2 += 1
else:
draws += 1
print(f"Player 1 wins: {player_1}")
print(f"Player 2 wins: {player_2}")
print(f"Draws: {draws}")
Player 1 wins: 117 Player 2 wins: 309 Draws: 574
๐ Congratulations! You've just created a Tic Tac Toe referee that can check the winner of any game! ๐