I am making a Tic Tac Toe game. In this, there are 2 modes. One is two player mode and other one is with AI. Two player mode is working all good. But AI mode is not working. The AI mode will be applied when there is a tick in the given checkbox, and one of the turns is played by AI. I have used minimax algorithm for AI execution. I am not getting what is wrong with the code as this is my first game using GUI (Tkinter). Please someone give me insights about what is wrong in it, or please correct my code. Thanks in advance.
from tkinter import *
from copy import deepcopy
import random
game = Tk()
game.title("TIC TAC TOE")
game.geometry("450x555")
#game.configure(bg = '#b3b3b3')
with_AI = Label(text = "Want to play with AI:", font = ("Helvatica", 15), fg = "#000000")
with_AI.grid(row = 0, column = 0, columnspan = 2, sticky = 'e')
yes_AI = IntVar()
Checkbutton(game, variable = yes_AI).grid(row = 0, column = 2, sticky = 'w')
textPlay = Label(text = "Start the Game!!!", font = ("Helvatica", 15), fg = "red")
textPlay.grid(row = 1, column = 0, columnspan = 3)
temp = random.choice([0, 1])
if temp == 0:
player = 'O'
else:
player = 'X'
stop_game = False
def minimax(states, depth, isMax, playerAI, scores):
result = checkWinner1()
if result != None:
return scores[result]
if isMax:
bestVal = -1000
for i in range(3):
for j in range(3):
if states[i][j] == 0:
states[i][j] = playerAI
moveVal = minimax(states, depth + 1, False, playerAI, scores)
states[i][j] = 0
bestVal = max(moveVal, bestVal)
return bestVal
else:
bestVal = 1000
for i in range(3):
for j in range(3):
if states[i][j] == 0:
if playerAI == 'X':
states[i][j] = 'O'
else:
states[i][j] = 'X'
moveVal = minimax(states, depth + 1, True, playerAI, scores)
states[i][j] = 0
bestVal = min(moveVal, bestVal)
return bestVal
def bestMove(states, playerAI, scores):
checkWinner1()
bestVal = -1000
for i in range(3):
for j in range(3):
if states[i][j] == 0:
moveVal = playerAI
moveVal = minimax(states, 0, False, playerAI, scores)
states[i][j] = 0
if moveVal > bestVal:
bestRow = i
bestColumn = j
bestVal = moveVal
return bestRow, bestColumn
def callback(r, c):
global player
global textPlay
global states
if player == 'X' and states[r][c] == 0 and stop_game == False:
board[r][c].configure(text = 'X', fg = '#f64c72')
states[r][c] = 'X'
player = 'O'
textPlay.config(text = "O's turn")
if yes_AI.get() == 1:
scores = {'X':-1, 'O':1, 'tie':0}
bestRow, bestColumn = bestMove(states, player, scores)
board[bestRow, bestColumn].configure(text = 'O', fg = '#f64c72')
states[bestRow, bestColumn] = 'O'
textPlay.config(text = "X's turn")
if player == 'O' and states[r][c] == 0 and stop_game == False:
board[r][c].configure(text = 'O', fg = '#f64c72')
states[r][c] = 'O'
player = 'X'
textPlay.config(text = "X's turn")
if yes_AI.get() == 1:
scores = {'X':1, 'O':-1, 'tie':0}
bestRow, bestColumn = bestMove(states, player, scores)
board[bestRow, bestColumn].configure(text = 'X', fg = '#f64c72')
states[bestRow, bestColumn] = 'X'
textPlay.config(text = "O's turn")
checkWinner()
def checkWinner1():
global stop_game
global states
win = None
win_color = '#85d139'
for i in range(3):
if states[i][0] == states[i][1] == states[i][2] != 0:
if states[i][0] == 'X':
win = 'X'
else:
win = 'O'
for i in range(3):
if states[0][i] == states[1][i] == states[2][i] != 0:
if states[0][i] == 'X':
win = 'X'
else:
win = 'O'
if states[0][0] == states[1][1] == states[2][2] != 0:
if states[1][1] == 'X':
win = 'X'
else:
win = 'O'
if states[2][0] == states[1][1] == states[0][2] != 0:
if states[1][1] == 'X':
win = 'X'
else:
win = 'O'
temp1 = 0
for i in range(3):
for j in range(3):
if states[i][j] == 0:
temp1 = 1
if temp1 == 0:
textPlay.configure(text = "It's a tie! Click on 'Reset' to play again.")
win = 'tie'
return win
def checkWinner():
global stop_game
global states
global board
win = None
win_color = '#85d139'
for i in range(3):
if states[i][0] == states[i][1] == states[i][2] != 0:
board[i][0].config(bg = win_color)
board[i][1].config(bg = win_color)
board[i][2].config(bg = win_color)
stop_game = True
if states[i][0] == 'X':
textPlay.config(text = "X wins! Click on 'Reset' to play again.")
win = 'X'
else:
textPlay.config(text = "O wins! Click on 'Reset' to play again.")
win = 'O'
for i in range(3):
if states[0][i] == states[1][i] == states[2][i] != 0:
board[0][i].config(bg = win_color)
board[1][i].config(bg = win_color)
board[2][i].config(bg = win_color)
stop_game = True
if states[0][i] == 'X':
textPlay.config(text = "X wins! Click on 'Reset' to play again.")
win = 'X'
else:
textPlay.config(text = "O wins! Click on 'Reset' to play again.")
win = 'O'
if states[0][0] == states[1][1] == states[2][2] != 0:
board[0][0].configure(bg = win_color)
board[1][1].configure(bg = win_color)
board[2][2].configure(bg = win_color)
stop_game = True
if states[1][1] == 'X':
textPlay.config(text = "X wins! Click on 'Reset' to play again.")
win = 'X'
else:
textPlay.config(text = "O wins! Click on 'Reset' to play again.")
win = 'O'
if states[2][0] == states[1][1] == states[0][2] != 0:
board[2][0].configure(bg = win_color)
board[1][1].configure(bg = win_color)
board[0][2].configure(bg = win_color)
stop_game = True
if states[1][1] == 'X':
textPlay.config(text = "X wins! Click on 'Reset' to play again.")
win = 'X'
else:
textPlay.config(text = "O wins! Click on 'Reset' to play again.")
win = 'O'
temp1 = 0
for i in range(3):
for j in range(3):
if states[i][j] == 0:
temp1 = 1
if temp1 == 0:
textPlay.configure(text = "It's a tie! Click on 'Reset' to play again.")
win = 'tie'
return win
f = [[0, 0, 0],
[0, 0, 0],
[0, 0, 0]]
board = [[0, 0, 0],
[0, 0, 0],
[0, 0, 0]]
states = [[0, 0, 0],
[0, 0, 0],
[0, 0, 0]]
def reset():
global stop_game
global player
global board
global states
for i in range(3):
for j in range(3):
board[i][j].configure(text = ' ', fg = '#ffda30', bg = "#242582")
states[i][j] = 0
stop_game = False
textPlay.configure(text = "Start the Game!!!")
temp = random.choice([0, 1])
if temp == 0:
player = 'O'
else:
player = 'X'
for i in range(3):
for j in range(3):
f[i][j] = Frame(game, width = 150, height = 150)
f[i][j].propagate(False)
f[i][j].grid(row = i+2, column = j, sticky = "nsew", padx = 1, pady = 1)
board[i][j] = Button(f[i][j], font = ("Helvatica", 70), bg = "#242582", fg = "#ffda30",
command = lambda r = i, c = j: callback(r, c))
board[i][j].pack(expand = True, fill = BOTH)
reset_game = Button(text = "Reset the game!", font = ("Helvatica", 15), bg = "#ffda30", fg = "#000000",
command = lambda :reset())
reset_game.grid(row = 5, column = 0, columnspan = 2, sticky = 'nsew')
quit_game = Button(text = "Quit game!", font = ("Helvatica", 15), bg = "#ffda30", fg = "red",
command = lambda :game.destroy())
quit_game.grid(row = 5, column = 2, sticky = 'nsew')
game.resizable(False, False)
game.mainloop()
In callback, inside 2nd 'if condition', you should add:
player = 'X'
and in the next one as player 'O' so as to change the players.