TicTacToe / tictactoe.py
OrifjonKenjayev's picture
Upload 2 files
14ebb49 verified
raw
history blame
3.05 kB
"""
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