Source code for Code.Board_script

from enum import Enum
from copy import deepcopy

[docs] class direction(Enum): ROW = 1 COL = 2 DIAG_TOP_BOTTOM = 3 DIAG_BOTTOM_TOP = 4
[docs] class Board: """ A class representing a Tic-Tac-Toe board. Attributes ---------- grid : list of list of int The game board, a 3x3 grid where 1 represents player X, -1 represents player O, and 0 represents an empty space. moves : list of tuple A list of moves made in the game, where each move is represented by a tuple (row, column, player). gameState : int The current state of the game: 0 for ongoing, 1 for player X win, -1 for player O win, and 9 for a draw. winningMove : tuple The winning move and its direction, if applicable. available_moves : set of tuple A set of available moves, each represented by a tuple (row, column). """ def __init__(self): """Initialize a new Tic-Tac-Toe board.""" self.grid = [[0, 0, 0], [0, 0, 0], [0, 0, 0]] self.moves = [] self.gameState = 0 self.winningMove = None self.available_moves = set([(i, j) for i in range(3) for j in range(3)])
[docs] def copy(self): """ Creates a deep copy of the current board state. Returns ------- Board A new Board instance with the copied state. """ board_copy = Board() board_copy.grid = deepcopy(self.grid) board_copy.moves = deepcopy(self.moves) board_copy.gameState = self.gameState board_copy.winningMove = self.winningMove board_copy.available_moves = self.available_moves.copy() return board_copy
[docs] def display_cell(self, i, j): """ Prints the content of a specified cell on the board. Parameters ---------- i : int The row index of the cell. j : int The column index of the cell. """ if self.grid[i][j] == 0: print(' ', end = '') elif self.grid[i][j] == 1: print(' X ', end = '') else: print(' O ', end = '')
[docs] def display(self, addSpace=False): """ Displays the entire board state in the console. Parameters ---------- addSpace : bool, optional If True, adds an extra newline after displaying the board. Default is False. """ for i in range(3): for j in range(3): self.display_cell(i, j) if j < 2: print('|', end='') else: print() if i < 2: print('-----------') if addSpace: print()
[docs] def display_player_name(self, player): """ Returns the display name of the player. Parameters ---------- player : int The player identifier (1 for 'X', -1 for 'O'). Returns ------- str The display name of the player. """ if player == 1: return "X" return "O"
[docs] def updateGameState(self, i, j, player): """ Updates the game state after a move. Parameters ---------- i : int The row index of the last move. j : int The column index of the last move. player : int The identifier of the player who made the last move. """ if len(self.moves) > 9 or self.gameState != 0: pass else: #check if the player has won on the row if self.playerWins_row(i, j, player): self.gameState = player self.winningMove = ((i, j), direction.ROW) return if self.playerWins_column(i, j, player): self.gameState = player self.winningMove = ((i, j), direction.COL) return won_on_diagonal = self.playerWins_diag(player) if won_on_diagonal[0]: self.gameState = player if won_on_diagonal[1] == 1: dir = direction.DIAG_TOP_BOTTOM else: dir = direction.DIAG_BOTTOM_TOP self.winningMove = ((i, j), dir)
[docs] def playerWins_row(self, i, j, player): """ Checks if a player wins by completing a row. Parameters ---------- i : int The row index of the last move. j : int The column index of the last move. player : int The identifier of the player who made the last move. Returns ------- bool True if the player wins by completing a row, False otherwise. """ if j == 0: return self.grid[i][j+1] == self.grid[i][j+2] == player if j == 1: return self.grid[i][j-1] == self.grid[i][j+1] == player return self.grid[i][j-2] == self.grid[i][j-1] == player
[docs] def playerWins_column(self, i, j, player): """ Checks if a player wins by completing a column. Parameters ---------- i : int The row index of the last move. j : int The column index of the last move. player : int The identifier of the player who made the last move. Returns ------- bool True if the player wins by completing a column, False otherwise. """ if i == 0: return self.grid[i+1][j] == self.grid[i+2][j] == player if i == 1: return self.grid[i-1][j] == self.grid[i+1][j] == player return self.grid[i-1][j] == self.grid[i-2][j] == player
[docs] def playerWins_diag(self, player): """ Checks if a player wins by completing a diagonal. Parameters ---------- player : int The identifier of the player. Returns ------- tuple A tuple containing a boolean indicating if a player wins and an integer indicating which diagonal. """ if self.grid[0][0] == self.grid[1][1] == self.grid[2][2] == player: #diagonal from top right corner to bottom left corner return (True, 1) return (self.grid[0][2] == self.grid[1][1] == self.grid[2][0] == player, 2)
[docs] def play(self, i, j, player): """ Plays a move on the board. Parameters ---------- i : int The row index for the move. j : int The column index for the move. player : int The identifier of the player making the move. Raises ------ Exception If the game is over or the cell is not empty. """ if self.gameState != 0 or len(self.moves) >= 9: text = "The game is a draw." if self.gameState == 0 else f"Player {self.display_player_name(self.gameState)} has won." raise Exception(text) elif self.grid[i][j] == 0: if len(self.moves) != 0 and self.moves[-1][2] == player: players_turn = 1 if player == -1 else -1 raise Exception(f"It's player {self.display_player_name(players_turn)}'s turn to play.") else: self.grid[i][j] = player self.moves.append((i, j, player)) self.updateGameState(i, j, player) self.available_moves.remove((i, j)) else: raise Exception(f"Cell [{i}, {j}] is not empty.")
[docs] def undo_last_move(self, return_move=False): """ Undoes the last move made on the board. Parameters ---------- return_move : bool, optional If True, returns the last move made. Default is False. Returns ------- tuple, optional The last move made (i, j, player) if return_move is True. Otherwise, nothing is returned. """ if len(self.moves) == 0: return (i, j, player) = self.moves.pop() self.grid[i][j] = 0 self.gameState = 0 # undoing the last move necessarily makes it so that the game cannot be over self.winningMove = None self.available_moves.add((i, j)) if return_move: return (i, j, player)
[docs] def get_square_representation(self, i, j): """ Returns a string representation of a cell's content. Parameters ---------- i : int The row index of the cell. j : int The column index of the cell. Returns ------- str The content of the cell represented as 'X', 'O', or '*' for an empty cell. """ if self.grid[i][j] == 0: return '*' if self.grid[i][j] == 1: return 'X' return 'O'
[docs] def get_representation(self): """ Generates a string representation of the entire board state. Returns ------- str A string representing the board's current state. """ representation = '' for i in range(3): for j in range(3): representation += self.get_square_representation(i, j) return representation
[docs] def isGameOver(self): """ Checks if the game is over. Returns ------- bool True if the game is over, False otherwise. """ return self.gameState != 0 or (self.gameState == 0 and len(self.moves) >= 9)