def test_player(self): player_1 = ttt.player(self.board_1) self.assertEqual(player_1, X) self.player_2 = ttt.player(self.board_2) self.assertEqual(self.player_2, O) self.player_3 = ttt.player(self.board_3) self.assertEqual(self.player_3, X)
def test_player_no_moves(self): player_board = \ [[self.EMPTY, self.EMPTY, self.EMPTY], [self.EMPTY, self.EMPTY, self.EMPTY], [self.EMPTY, self.EMPTY, self.EMPTY]] self.assertEqual(self.X, ttt.player(player_board))
def test_cs50_example(): board = [[None, "X", "O"], ["O", "X", None], ["X", None, "O"]] assert ttt.player(board) is ttt.X next_move = ttt.minimax(board) expected = (2, 1) assert next_move == expected
def ignore_test_next_move(): board = [["O", None, None], [None, None, None], ["X", None, "X"]] assert ttt.player(board) is ttt.O next_move = ttt.minimax(board) expected = (2, 1) assert next_move is expected
def result(board, action): """ Returns the board that results from making move (i, j) on the board. """ ## Create deep copy by iterating through board ## note - this only works for a 3 x 3 board board_copy = [[EMPTY, EMPTY, EMPTY], [EMPTY, EMPTY, EMPTY], [EMPTY, EMPTY, EMPTY]] for row in range(3): for cell in range(3): board_copy[row][cell] = board[row][cell] ## Check if action out of bounds if action[0] < 0 or action[0] > 2: print('Index out of bounds') raise IndexError if action[1] < 0 or action[1] > 2: print('Index out of bounds') raise IndexError ## Check if action over writes: if board_copy[action[0]][action[1]] is not None: print('Index overwrites action') raise ValueError ## Otherwise return deep copy with new action, ## using player function to determine whether to add X or O board_copy[action[0]][action[1]] = player(board_copy) return board_copy
def test_player(self): board = [[tictactoe.EMPTY, tictactoe.EMPTY, tictactoe.EMPTY], [tictactoe.EMPTY, tictactoe.EMPTY, tictactoe.EMPTY], [tictactoe.EMPTY, tictactoe.EMPTY, tictactoe.EMPTY]] player = tictactoe.player(board) self.assertEqual(player, tictactoe.X)
def make_move(): btn_text.set(tictactoe.player(self.state)) btn["state"] = "disabled" self.state = tictactoe.result(self.state, (x, y)) if tictactoe.terminal(self.state): self.game_over() return self.opponent_plays()
def test_player(self): board = [ [tictactoe.EMPTY, tictactoe.EMPTY, tictactoe.EMPTY], [tictactoe.EMPTY, tictactoe.EMPTY, tictactoe.EMPTY], [tictactoe.EMPTY, tictactoe.EMPTY, tictactoe.EMPTY], ] # Check first player result = tictactoe.player(board) self.assertEqual(result, tictactoe.X) # Check second player board[0][0] = tictactoe.X result = tictactoe.player(board) self.assertEqual(result, tictactoe.O) # Check third player board[0][1] = tictactoe.O result = tictactoe.player(board) self.assertEqual(result, tictactoe.X)
def minimax(board): """ Returns the optimal action for the current player on the board. """ def max_value(state, depth=0): if ttt.terminal(state): return (None, ttt.utility(state)) v = (None, -2) for action in ttt.actions(state): v = max( v, (action, min_value(ttt.result(state, action), depth + 1)[1] - (depth / 10)), key=lambda x: x[1]) return v def min_value(state, depth=0): if ttt.terminal(state): return (None, ttt.utility(state)) v = (None, 2) for action in ttt.actions(state): v = min( v, (action, max_value(ttt.result(state, action), depth + 1)[1] + (depth / 10)), key=lambda x: x[1]) return v if ttt.player(board) == X: return max_value(board)[0] elif ttt.player(board) == O: return min_value(board)[0]
def opponent_plays(self): player = tictactoe.player(self.state) if player == tictactoe.PLAYER_O: _, action = tictactoe.min_value(self.state) else: _, action = tictactoe.max_value(self.state) btn, btn_text = self.buttons[action] btn_text.set(player) btn["state"] = "disabled" self.state = tictactoe.result(self.state, action) if tictactoe.terminal(self.state): self.game_over()
def minimax(board): """ Returns the optimal action for the current player on the board. """ if terminal(board) is True: return None # Code for player O if player(board) is O: v = float("inf") optimal = [] for action in actions(board): actionvalue = MaxValue(result(board, action)) if actionvalue < v: optimal.clear() optimal.append(action) v = actionvalue elif actionvalue == v: optimal.append(action) i = random.randrange(len(optimal)) return optimal[i] # Code for player X else: """ As any first move is expected to tie playing optimally, just randomize the first move to be quicker To make it more interesting, we take a random move between all the optimal sollutions so that the computer wont always play the same game. """ if board == [[EMPTY, EMPTY, EMPTY], [EMPTY, EMPTY, EMPTY], [EMPTY, EMPTY, EMPTY]]: return (random.randrange(3), random.randrange(3)) else: v = float("-inf") optimal = [] for action in actions(board): actionvalue = MinValue(result(board, action)) if actionvalue > v: optimal.clear() optimal.append(action) v = actionvalue elif actionvalue == v: optimal.append(action) i = random.randrange(len(optimal)) return optimal[i]
def test_late_victory(): """ This case is interesting, though moving to (2, 1) would be an immediate victory, moving to (0, 0) would also end in a late victory. The latter is picked due to tuple ordering: min([(score, action)]) Where (0, 0) < (2, 1) """ board = [[None, "O", "X"], ["X", "O", None], ["X", None, None]] assert ttt.player(board) is ttt.O early_win = (2, 1) late_win = (0, 0) assert ttt.minimax(board) in [early_win, late_win]
def minimax(board): """ Returns the optimal action for the current player on the board. To be quicker if we detect a winning move we take it, not taking into account other moves """ if terminal(board) is True: return None # Code for player O if player(board) is O: v = float("inf") for action in actions(board): actionvalue = MaxValue(result(board, action)) if actionvalue == -1: return action if actionvalue < v: optimal = action v = actionvalue return optimal # Code for player X else: """ As any first move is expected to tie playing optimally, just randomize the first move to be quicker """ if board == [[EMPTY, EMPTY, EMPTY], [EMPTY, EMPTY, EMPTY], [EMPTY, EMPTY, EMPTY]]: return (random.randrange(3), random.randrange(3)) else: v = float("-inf") for action in actions(board): actionvalue = MinValue(result(board, action)) if actionvalue == 1: return action if actionvalue > v: optimal = action v = actionvalue return optimal
for j in range(3): rect = pygame.Rect(tile_origin[0] + j * tile_size, tile_origin[1] + i * tile_size, tile_size, tile_size) pygame.draw.rect(screen, white, rect, 3) if board[i][j] != tct.EMPTY: move = moveFont.render(board[i][j], True, white) moveRect = move.get_rect() moveRect.center = rect.center screen.blit(move, moveRect) row.append(rect) tiles.append(row) game_over = tct.terminal(board) player = tct.player(board) # Show title if game_over: winner = tct.winner(board) if winner is None: title = f"Game Over: Tie." else: title = f"Game Over: {winner} wins." elif user == player: title = f"Play as {user}" else: title = f"Computer thinking..." title = largeFont.render(title, True, white) titleRect = title.get_rect() titleRect.center = ((width / 2), 30)
def test_o_moves_after_any_x(coord): init = ttt.initial_state() x, y = coord init[x][y] = ttt.X assert ttt.player(init) == ttt.O
def test_x_moves_first(): init = ttt.initial_state() assert ttt.player(init) == ttt.X
def test_player_empty_board(self): self.assertEqual(player(initial_state()), X)
def test_player_non_empty_2(): board = [["X", "O", EMPTY], [EMPTY, EMPTY, EMPTY], [EMPTY, EMPTY, EMPTY]] assert ttt.player(board) == "X"
import tictactoe as ttt board = ttt.test_state() while not (ttt.terminal(board)): move = ttt.minimax(board) print(ttt.player(board)) print(move) board = ttt.result(board, move) print(board) print(f"The winner is {ttt.winner(board)}")
def test_player_Os_move(self): board = [[X, EMPTY, EMPTY], [EMPTY, EMPTY, EMPTY], [EMPTY, EMPTY, EMPTY]] self.assertEqual(player(board), O)
def test_player_initial_state(self): self.assertEqual(player(initial_state()), X)
def test_first_move(self): board = [[EMPTY, EMPTY, EMPTY], [EMPTY, EMPTY, EMPTY], [EMPTY, EMPTY, EMPTY]] self.assertEqual(player(board), "X")
def test_o_turn(self): board = [[EMPTY, EMPTY, "X"], [EMPTY, "X", EMPTY], [EMPTY, EMPTY, "O"]] self.assertEqual(player(board), "O")
from tictactoe import initial_state from tictactoe import actions from tictactoe import player from tictactoe import result from tictactoe import winner from tictactoe import terminal from tictactoe import utility from tictactoe import minimax X = "X" O = "O" EMPTY = None myboard = [[X, O, EMPTY], [O, EMPTY, O], [X, O, X]] # z = [(i,j) for i in range(len(myboard)) for j in range(len(myboard[0])) if myboard[i][j] == EMPTY] # print(z) # print(actions(myboard)) # print(result(myboard,(1,1))) # print(winner(myboard)) # print(terminal(myboard)) # print(utility(myboard)) print(player(myboard)) print(minimax(myboard))
def test_player_o_turn_board(self): x_board = [[EMPTY, O, EMPTY], [X, EMPTY, EMPTY], [EMPTY, X, EMPTY]] self.assertEqual(player(x_board), O)
def test_player_non_empty_3(): board = [["X", EMPTY, "X"], ["O", "X", "O"], ["X", "O", "X"]] assert ttt.player(board) == "O"
def test_player_x_turn_board(self): o_board = [[EMPTY, X, EMPTY], [O, EMPTY, EMPTY], [EMPTY, EMPTY, EMPTY]] self.assertEqual(player(o_board), X)
def test_player1(self): board = ttt.initial_state() self.assertEqual("X", ttt.player(board))
tile_origin[0] + j * tile_size, tile_origin[1] + i * tile_size, tile_size, tile_size ) pygame.draw.rect(screen, white, rect, 3) if board[i][j] != ttt.EMPTY: move = moveFont.render(board[i][j], True, white) moveRect = move.get_rect() moveRect.center = rect.center screen.blit(move, moveRect) row.append(rect) tiles.append(row) game_over = ttt.terminal(board) player = ttt.player(board) # Show title if game_over: winner = ttt.winner(board) if winner is None: title = f"Game Over: Tie." else: title = f"Game Over: {winner} wins." elif user == player: title = f"Play as {user}" else: title = f"Computer thinking..." title = largeFont.render(title, True, white) titleRect = title.get_rect() titleRect.center = ((width / 2), 30)
def test_player_empty_board(): board = [[EMPTY, EMPTY, EMPTY], [EMPTY, EMPTY, EMPTY], [EMPTY, EMPTY, EMPTY]] assert ttt.player(board) == "X"