You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python Tkinter开发Hangman游戏时chances变量未定义问题求助

问题分析

你遇到的chances未定义错误,核心原因是嵌套函数main_loop里误用了global chances:chances是外层gameEasy函数的局部变量,而非模块级的全局变量,global关键字仅用于引用最外层(模块级)的变量,对嵌套函数访问外层局部变量无效。

解决方案

将main_loop中的global chances替换为nonlocal chances,nonlocal专门用于嵌套函数访问外层函数的局部变量。同时修正代码中其他逻辑问题:

  1. 原while循环每次执行后都会break,实际仅运行一次,改为if语句更合理;
  2. 删除else块中多余的chances -=1,避免机会数被错误减少;
  3. 用Toplevel()替代Tk()创建游戏窗口,避免多主循环冲突;
  4. 移除多余的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 23:55:55