"""
Tic Tac Toe Player
"""
import math
import copy
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.
"""
countx=0
counto=0
for i in range(0,3):
for j in range(0,3):
if board[i][j]==X:
countx+=1
if board[i][j]==O:
counto+=1
if counto>countx:
return X
if countx>counto:
return O
def actions(board):
"""
Returns set of all possible actions (i, j) available on the board.
"""
allaction=set()
for i in range(0,3):
for j in range(0,3):
if board[i][j]==EMPTY:
print(i,j)
allaction.add((i,j))
return allaction
def result(board, action):
"""
Returns the board that results from making move (i, j) on the board.
"""
current_player=player(board)
new_all_actions=actions(board)
if action not in new_all_actions:
raise Exception("move not in the set ")
i,j=action
copy_board=copy.deepcopy(board)
copy_board[i][j]=current_player
return copy_board
def check_row(board,player):
for i in range(0,3):
if board[i][0]==player and board[i][1]==player and board[i][2]==player:
return True
return False
def check_column(board,player):
for i in range(len(board)-1):
if board[0][i]==player and board[1][i]==player and board[2][i]==player:
return True
return False
def check_diagonals(board,player):
if board[0][0]==player and board[1][1]==player and board[2][2]==player:
return True
elif board[0][2]==player and board[1][1]==player and board[2][0]==player:
return True
return False
def winner(board):
"""
Returns the winner of the game, if there is one.
"""
if check_column(board,X)==True or check_row(board,X)==True or check_diagonals(board,X)==True:
return X
elif check_column(board,O)==True or check_row(board,O)==True or check_diagonals(board,O)==True:
return O
return None
def terminal(board):
"""
Returns True if game is over, False otherwise.
"""
for i in range(0,3):
for j in range(0,3):
if board[i][j]==EMPTY:
return False
if winner(board)==X or winner(board)==O:
return True
else:
return True
def utility(board):
"""
Returns 1 if X has won the game, -1 if O has won, 0 otherwise.
"""
if terminal(board)==False:
raise Exception("game not over")
if winner(board)==X:
return 1
if winner(board)==O:
return -1
else:
return 0
def max_value(board):
v=-math.inf
if terminal(board):
return utility(board)
for action in actions(board):
v=max(v,min_value(result(board,action)))
return v
def min_value(board):
v=math.inf
if terminal(board):
return utility(board)
for action in actions(board):
v=min(v,max_value(result(board,action)))
return v
def minimax(board):
if terminal(board):
return None
elif player(board)==X:
max_variable=-math.inf
max_index=0
score_play=[]
for action in actions(board):
score_play.append(min_value(result(board,action)),action)
for i in range(len(score_play)-1):
if score_play[i][0]>max_variable:
max_variable=score_play[i][0]
max_index=i
return score_play[max_index][1]
#its returns min of max_value of all possible boards from the result
elif player(board)==O:
min_varible=math.inf
min_index=0
score_play=[]
for action in actions(board):
score_play.append(max_value(result(board,action),action))
for j in range(len(score_play)-1):
if score_play[j][0]<min_varible:
min_varible=score_play[j][0]
min_index=j
for q in score_play[min_index][1] :
print(q)
return score_play[min_index][1]
this is my code for a tic tac toe ai. On runnig it it shows the following error
Traceback (most recent call last): File "C:\Users\Dell\Downloads\tictactoe\tictactoe\runner.py", line 116, in board = ttt.result(board, move) File "C:\Users\Dell\Downloads\tictactoe\tictactoe\tictactoe.py", line 66, in result raise Exception("move not in the set ") Exception: move not in the set
on further looking i got to know that the action passed to the result function is none but dont know why
I tried debugging it for a long time . the only error that can happen is maybe in the minmax function
There are these issues:
terminal
returns False
for any board that has an empty spot. You should only start the empty spot check when it is already verified that there is no winner. NB: the if..else
is overkill, since in both cases you return True, so just ... return True without condition. Also, you can use the in
operator to check if a row has EMPTY
:
def terminal(board):
if not winner(board): # Only check for empty spot when no winner
for row in board:
if EMPTY in row:
return False
return True # No condition needed
player
can return None
when the two counters are equal. The function should never return None
. Assuming X is the first player, you should return X when the count is equal and O otherwise:
if counto==countx:
return X
return O
check_column
only iterates twice with range(len(board)-1)
, but it should iterate 3 times. So:
for i in range(len(board)): # not -1 !!
In minimax
parentheses are put wrongly in score_play.append(max_value(result(board,action),action))
. Both max_value
and append
should be called with one argument, so:
score_play.append((max_value(result(board,action)),action))
A similar change is needed where you call min_value
In minimax
the loop over score_play
does not visit the last entry when having range(len(score_play)-1)
. The loop should be:
for i in range(len(score_play)):
Change this in both places where this occurs.
NB: You could have detected all of these issues yourself if you would have used a debugger, stepping through the code, setting break points and inspecting variables.