我正在用Tkinter编写井字游戏。当一个用户获胜时,将出现一个带有“重新启动”按钮的“顶层”窗口,该窗口必须重新启动该程序,但是单击该程序时会收到意外错误。我知道我的获胜者检查功能很愚蠢,但是我可以根据当前的知识水平编写更好的软件。 错误消息:
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
这是代码:
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()
此外,如果您对isWinner功能有更明智的建议,可以与我分享吗?
答案 0 :(得分:1)
这应该可以解决您的问题。
您需要在函数外部定义一个变量,以将其与global一起使用,并让main()使用该变量。另外,如果要在命令中调用任何函数并将变量传递给该函数,请始终使用lambda。
from tkinter import *
turn = True
btns = None
root = 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=lambda: 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
global root
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()