I was writing a Tic-Tac-Toe game using Tkinter. When one user wins, a Toplevel window appears with Restart button, that must restart the program, but I receive unexpected error when I click on it. I know my winner checking function is stupid, but I could write a better one with my current knowledge level. The error message:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\Eldiiar Raiymkulov\AppData\Local\Programs\Python\Python36-32\lib\tkinter\__init__.py", line 1699, in __call__
return self.func(*args)
File "C:\Users\Eldiiar Raiymkulov\Desktop\xo2.py", line 62, in <lambda>
command=lambda x=x, y=y: clicked(y, x)))
File "C:\Users\Eldiiar Raiymkulov\Desktop\xo2.py", line 15, in clicked
isWinner(char)
File "C:\Users\Eldiiar Raiymkulov\Desktop\xo2.py", line 46, in isWinner
topMessage(char)
File "C:\Users\Eldiiar Raiymkulov\Desktop\xo2.py", line 30, in topMessage
topButton = Button(top, text="Restart", command=restart(root))
NameError: name 'root' is not defined
And here is the code:
from tkinter import *
turn = True
btns = None
def clicked(y, x):
global turn, btns
char = ""
if turn:
char = "X"
else:
char = "O"
btns[y][x].config(text=char,
state=DISABLED)
isWinner(char)
turn = not turn
def restart(root):
global turn
turn = True
root.destroy()
main()
def topMessage(char):
global root
top = Toplevel()
top.title("Congratulations!")
topText = Label(top, text=f"{char} is a winner!")
topButton = Button(top, text="Restart", command=restart(root))
topText.grid(row=0)
topButton.grid(row=1)
def isWinner(char):
global root
#horizontal
if (((btns[1][1].cget("text") == char) and (btns[1][2].cget("text") == char) and (btns[1][3].cget("text") == char)) or
((btns[2][1].cget("text") == char) and (btns[2][2].cget("text") == char) and (btns[2][3].cget("text") == char)) or
((btns[3][1].cget("text") == char) and (btns[3][2].cget("text") == char) and (btns[3][3].cget("text") == char)) or
#vertical
((btns[1][1].cget("text") == char) and (btns[2][1].cget("text") == char) and (btns[3][1].cget("text") == char)) or
((btns[1][2].cget("text") == char) and (btns[2][2].cget("text") == char) and (btns[3][2].cget("text") == char)) or
((btns[1][3].cget("text") == char) and (btns[2][3].cget("text") == char) and (btns[3][3].cget("text") == char)) or
#diagonal
((btns[1][1].cget("text") == char) and (btns[2][2].cget("text") == char) and (btns[3][3].cget("text") == char)) or
((btns[1][3].cget("text") == char) and (btns[2][2].cget("text") == char) and (btns[3][1].cget("text") == char))):
topMessage(char)
def main():
global btns
root = Tk()
root.title("X and O of Daniar")
root.resizable(False, False)
btns = [None]
for y in range(1, 4):
row = [None]
for x in range(1, 4):
row.append(Button(root,
width=5,
height=3,
font="time 12 bold",
command=lambda x=x, y=y: clicked(y, x)))
row[x].grid(row=y, column=x)
btns.append(row)
Button(root,
text="Restart",
width=5,
command=lambda: restart(root)).grid(row=4, column=2)
root.mainloop()
main()
Also, if you have any smarter suggestions about isWinner functions, could you please share them with me?