Python Tkinter开发Hangman游戏时chances变量未定义问题求助
问题分析
你遇到的chances未定义错误,核心原因是嵌套函数main_loop里误用了global chances:chances是外层gameEasy函数的局部变量,而非模块级的全局变量,global关键字仅用于引用最外层(模块级)的变量,对嵌套函数访问外层局部变量无效。
解决方案
将main_loop中的global chances替换为nonlocal chances,nonlocal专门用于嵌套函数访问外层函数的局部变量。同时修正代码中其他逻辑问题:
- 原
while循环每次执行后都会break,实际仅运行一次,改为if语句更合理; - 删除
else块中多余的chances -=1,避免机会数被错误减少; - 用
Toplevel()替代Tk()创建游戏窗口,避免多主循环冲突; - 移除多余的
StringVar()赋值,优化代码冗余。
修正后的完整代码
from tkinter import * from tkinter import messagebox import random # 主窗口初始化 window = Tk() window.geometry('450x250') window.resizable(False, False) window.title("Hangman") window.canvas = Canvas(window, width=450, height=250) window.canvas.pack() def gameEasy(*args): # 用Toplevel创建子窗口,避免多主循环问题 hangman = Toplevel(window) hangman.geometry('450x200') hangman.resizable(False, False) hangman.title("Hangman") hangman.canvas = Canvas(hangman, width=450, height=200) hangman.canvas.pack() # 绘制初始绞架 hangman.canvas.create_line(50, 120, 70, 120) hangman.canvas.create_line(59, 120, 59, 80) hangman.canvas.create_line(59, 80, 39, 80) hangman.canvas.create_line(39, 80, 39, 85) # 加载单词库并随机选词 wordlistEasy = '''cat dog apple stars movie hammer sprint farmer''' wordlistEasy = wordlistEasy.split(' ') word = random.choice(wordlistEasy) letterguessed = [] chances = len(word) + 2 correct = 0 flag = 0 X1 = 75 Y1 = 120 X2 = 85 Y2 = 120 # 绘制单词下划线 for i in word: X1 += 12 X2 += 12 hangman.canvas.create_line(X1, Y1, X2, Y2, dash=(8,1)) def main_loop(*args): Guess = str(GuessInput.get()) # 用nonlocal访问外层gameEasy函数的局部变量 nonlocal chances, flag, correct incorrectLabel.config(text="") if chances != 0 and flag == 0: chances -= 1 # 输入合法性校验 if not Guess.isalpha() and Guess != "": incorrectLabel.config(text="Please input a LETTER!") chances += 1 elif len(Guess) > 1 and (Guess != word): incorrectLabel.config(text="Please input only one letter!") chances += 1 elif (Guess in letterguessed) and Guess != "": incorrectLabel.config(text="Letter already guessed!") chances += 1 else: letterguessed.append(Guess) letterList.config(text=(letterguessed)) chancesLabel.config(text=f"Chances left: {chances}") # 校验字母是否在单词中,绘制正确字母 if Guess in word: correct += word.count(Guess) temp_X = 75 + 12 for char in word: if char == Guess: hangman.canvas.create_text(temp_X, 115, text=Guess) temp_X +=12 # 判断是否猜对全部字母 if correct == len(word): flag = 1 messagebox.showinfo("Success!", f"You guessed the word: {word}!") hangman.destroy() # 处理机会耗尽的情况 if chances == 0 and flag ==0: messagebox.showinfo("Game Over", f"Out of chances! The word was: {word}") hangman.destroy() GuessInput.delete(0,"end") # 清空输入框 # 输入框与按钮初始化 GuessInput = Entry(hangman, width=8, bd="1") GuessInput.place(x=15, y=31) GuessInput.focus_force() Guessbtn = Button(hangman, text="Guess", width=7, bd="1", command=main_loop).place(x=75, y=28) hangman.bind('<Return>', main_loop) # 状态标签初始化 lettersLabel = Label(hangman, text="Guessed letters:").place(x=220, y=5) letterList = Label(hangman, text="") letterList.place(x=220, y=20) chancesLabel = Label(hangman, text=f"Chances left: {chances}") chancesLabel.place(x=12, y=5) incorrectLabel = Label(hangman, text="", fg="red") incorrectLabel.place(x=12, y=52) def exit(*args): messagebox.showinfo("Thank You", "Thanks for playing!") window.destroy() # 主窗口控件初始化 mainlabel = Label(window, text="Welcome to Hangman", font=("Arial Bold",14)).place(x=120, y=5) introMessage = Message(window, text="This is a simple hangman program using Tkinter. To play, simply select a difficulty, to leave, select quit!", width=280) introMessage.place(x=80, y=30) difficultyLabel = Label(window, text="Select a difficulty", font=("Arial Bold",9)).place(x=170, y=70) easybtn = Button(window, text = "Easy", width=10, bd="1", command=gameEasy).place(x=182, y=95) hardbtn = Button(window, text = "Hard", width=10, bd="1").place(x=182, y=120) window.canvas.create_line(175,150,265,150) rulesbtn = Button(window, text = "Rules", width=10, bd="1").place(x=182, y=155) quitbtn = Button(window, text = "Quit", width=10, bd="1", command=exit).place(x=182, y=180) window.mainloop()
内容的提问来源于stack exchange,提问作者David Blackwell
相关产品推荐
相关产品推荐

