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 | |