def _run_play_scenarios(self, scenarios): ''' Runs 'play' test scenarios. This method verifies whether the engine outputs expected values (move) for the specified board arrangements. Args: scenarios: A list of test scenarios given as dictionaries: { 'board': *numpy array of arrays with values P1, P2 or EMPTY*, 'player': *current player: P1 or P2*, 'expected_moves': *list of moves given as tuples (x, y)* } ''' for scenario in scenarios: board = scenario['board'] player = scenario['player'] expected_moves = scenario['expected_moves'] move = self._engine.next_move(board, player) self.assertTrue(move in expected_moves, self._MESSAGE_PLAY_TEST.format(expected_moves, move, util.board_to_str(board)))
def _run_state_scenarios(self, scenarios): ''' Runs 'state' scenarios. This method verifies whether the engine correctly analyzes the current state of the game (board). Args: scenarios: A list of test scenarios given as dictionaries: { 'board': numpy array of arrays with values P1, P2 or EMPTY, 'expected_state': either P1_WON, P2_WON or DRAW } ''' for scenario in scenarios: board = scenario['board'] expected_state = scenario['expected_state'] state = self._engine.get_state(board) msg = self._MESSAGE_STATE_TEST.format( self._STATE_NAMES[expected_state], self._STATE_NAMES[state], util.board_to_str(board)) self.assertEqual(state, expected_state, msg)
def __str__(self) -> str: retVal = f"Round: {self.state['round']}\n" retVal += f"Active Player: {self.state.activePlayer}\n" for p, n in self.state.cellCount().items(): retVal += f"Living {p}: {n}\n" retVal += util.board_to_str(self.last_state.board, self.last_move) return retVal
def main(): ''' Entry method of the Tic-Tac-Toe application. ''' sys.stdout.write('Cross (X) or nought (0)? [default: O]: ') player_choice = sys.stdin.readline().strip().upper() human = (player_choice == 'X') and engine.P1 or engine.P2 game = Game() game.start() # Print the board only if human player plays the 'X' if human == engine.P1: print(util.board_to_str(game.board)) while not game.is_over(): if game.player == human: move = read_move() else: move = None # If the move is None, get move from AI engine game.play(move) print(util.board_to_str(game.board)) message = ['The game is over. '] if game.is_draw(): message.append('It\'s a draw!') else: if game.has_cross_won(): message.append('Player 1 has won!') else: message.append('Player 2 has won!') print(''.join(message)) return 0
def _run_unbeatable(self, board, move_history, player, human): ''' Checks every possible game permutation for computer defeat. Args: board: The game board represented by numpy 3x3 array of arrays. move_history: An ordered list of tuples (x, y) representing moves. player: Current player. human: Human player. ''' state = self._engine.get_state(board) if state != IN_PROGRESS: computer = self._engine.get_opponent(human) self.assertFalse(self._has_computer_lost(state, human), self._MESSAGE_UBEATABLE_TEST .format(self._PLAYER_CHAR[computer], move_history, util.board_to_str(board))) return if player == human: for move in self._engine.get_legal_moves(board): new_board = board.copy() new_move_history = copy.copy(move_history) new_move_history.append(move) new_board[move[0], move[1]] = player self._run_unbeatable(new_board, new_move_history, self._engine.get_opponent(player), human) else: move = self._engine.next_move(board, player) move_history.append(move) board[move[0], move[1]] = player self._run_unbeatable(board, move_history, self._engine.get_opponent(player), human)