Background
I am currently participating in a tic-tac-toe coding challenge. During their move, each participant is given the board state and their team, X or O. The blank board is:
[[' ',' ',' '],[' ',' ',' '],[' ',' ',' ']]
With 'X' and 'O' being added to the board, for example:
[[' ',' ',' '],[' ','X',' '],[' ','O',' ']]
I have developed a minimax algorithm with alpha-beta pruning in Python 2.7 and it plays perfectly (Please see code).
Link to challenge rules: https://ccpc.codecraftworks.com/python
Problem
The algorithm will always win or tie. In the event of a tie, the winner is determined by the computation time. I need to decrease the average time taken per move from 0.195 seconds to less than 500,000 nanoseconds (0.0005 seconds)
Possible Reasons for the Problem
- Incorrect implementation of minimax algorithm
- Incorrect implementation of alpha beta pruning.
Possible Solutions
I have tried to separate the min and max functions and apply them separately, however that didn't work. I searched stack overflow for other possible ways to decrease computation time in my program, but I couldn't find anything.
Code
Note 1: getGameState(), getTeam(), and submitMove(row, col) are predefined functions provided by the back end of the coding challenge . You can test the code by uploading the file here: https://ccpc.codecraftworks.com/
team = getTeam()
value_dict = {
"X": 1,
"tie": 0,
"O": -1
}
def winner(board):
for i in range(len(board)):
if board[i][0] == board[i][1] and board[i][1] == board[i][2]:
if board[i][0] == "X":
return "X"
if board[i][0] == "O":
return "O"
for i in range(len(board[0])):
if board[0][i] == board[1][i] and board[1][i] == board[2][i]:
if board[0][i] == "X":
return "X"
if board[0][i] == "O":
return "O"
if board[0][0] == board[1][1] and board[1][1] == board[2][2]:
if board[0][0] == "X":
return "X"
if board[0][0] == "O":
return "O"
if board[2][0] == board[1][1] and board[1][1] == board[0][2]:
if board[2][0] == "X":
return "X"
if board[2][0] == "O":
return "O"
for row in board:
for cell in row:
if cell == ' ':
return "continue"
return "tie"
def minimax(board, depth, is_max, n, alpha = float('-inf'), beta = float('inf')):
check_winner = winner(board)
if check_winner != "continue":
return value_dict[check_winner]
if is_max:
best_score = float('-inf')
for i in range(n):
for j in range(n):
if board[i][j] == " ":
board[i][j] = "X"
score = minimax(board, depth+1, False, n, alpha, beta)
board[i][j] = " "
best_score = max(score, best_score)
alpha = max(alpha, score)
if beta >= alpha:
pass
return best_score
else:
best_score = float('inf')
for i in range(n):
for j in range(n):
if board[i][j] == " ":
board[i][j] = "O"
score = minimax(board, depth+1, True,n, alpha, beta)
board[i][j] = " "
best_score = min(score, best_score)
beta = min(beta, score)
if alpha >= beta:
pass
return best_score
def calcMove():
board = getGameState()
if team =="X":
score = - 2
x = -1
y = -1
for i in range(len(board)):
for j in range(len(board[0])):
if board[i][j] == ' ':
board[i][j] = "X"
curr_score = minimax(board,0,False, len(board))
board[i][j] = ' '
if curr_score > score:
score = curr_score
x = i
y = j
elif team =="O":
score = 2
x = 1
y = 1
for i in range(len(board)):
for j in range(len(board[0])):
if board[i][j] == ' ':
board[i][j] = "O"
curr_score = minimax(board,0,True, len(board))
board[i][j] = ' '
if curr_score < score:
score = curr_score
x = i
y = j
submitMove(x,y)
value_dict
lookup table at the beginning of the program. \$\endgroup\$