Spaces:
Sleeping
Sleeping
| """ | |
| Tic Tac Toe Player | |
| """ | |
| import math | |
| X = "X" | |
| O = "O" | |
| EMPTY = None | |
| def initial_state(): | |
| """ | |
| Returns starting state of the board. | |
| """ | |
| return [[EMPTY, EMPTY, EMPTY], | |
| [EMPTY, EMPTY, EMPTY], | |
| [EMPTY, EMPTY, EMPTY]] | |
| def player(board): | |
| """ | |
| Returns player who has the next turn on a board. | |
| """ | |
| x_count = sum(row.count(X) for row in board) | |
| o_count = sum(row.count(O) for row in board) | |
| return X if x_count == o_count else O | |
| def actions(board): | |
| """ | |
| Returns set of all possible actions (i, j) available on the board. | |
| """ | |
| return {(i, j) for i in range(3) for j in range(3) if board[i][j] == EMPTY} | |
| def result(board, action): | |
| """ | |
| Returns the board that results from making move (i, j) on the board. | |
| """ | |
| if board[action[0]][action[1]] is not EMPTY: | |
| raise Exception("Invalid action") | |
| new_board = [row[:] for row in board] | |
| new_board[action[0]][action[1]] = player(board) | |
| return new_board | |
| def winner(board): | |
| """ | |
| Returns the winner of the game, if there is one. | |
| """ | |
| for line in board: # Check rows | |
| if line[0] == line[1] == line[2] and line[0] is not None: | |
| return line[0] | |
| for col in range(3): # Check columns | |
| if board[0][col] == board[1][col] == board[2][col] and board[0][col] is not None: | |
| return board[0][col] | |
| if board[0][0] == board[1][1] == board[2][2] and board[0][0] is not None: # Check diagonal | |
| return board[0][0] | |
| if board[0][2] == board[1][1] == board[2][0] and board[0][2] is not None: # Check anti-diagonal | |
| return board[0][2] | |
| return None | |
| def terminal(board): | |
| """ | |
| Returns True if game is over, False otherwise. | |
| """ | |
| return winner(board) is not None or all(cell is not EMPTY for row in board for cell in row) | |
| def utility(board): | |
| """ | |
| Returns 1 if X has won the game, -1 if O has won, 0 otherwise. | |
| """ | |
| win = winner(board) | |
| if win == X: | |
| return 1 | |
| elif win == O: | |
| return -1 | |
| else: | |
| return 0 | |
| def minimax(board): | |
| """ | |
| Returns the optimal action for the current player on the board. | |
| """ | |
| if terminal(board): | |
| return None | |
| turn = player(board) | |
| def max_value(board): | |
| if terminal(board): | |
| return utility(board), None | |
| v = -math.inf | |
| best_move = None | |
| for action in actions(board): | |
| val, _ = min_value(result(board, action)) | |
| if val > v: | |
| v = val | |
| best_move = action | |
| return v, best_move | |
| def min_value(board): | |
| if terminal(board): | |
| return utility(board), None | |
| v = math.inf | |
| best_move = None | |
| for action in actions(board): | |
| val, _ = max_value(result(board, action)) | |
| if val < v: | |
| v = val | |
| best_move = action | |
| return v, best_move | |
| if turn == X: | |
| _, move = max_value(board) | |
| else: | |
| _, move = min_value(board) | |
| return move | |