使用global关键字后仍提示player_number未定义的Tkinter问题
Tkinter石头剪刀布程序
player_number未定义问题解决 问题情况
我用Tkinter开发带GUI的石头剪刀布程序,未完成的run()函数里提示player_number未定义:
def run(): result.grid(column=3, row=1) if player_number == "1": rock.grid(column=2, row=2) add_fillers() choose_player_number() run()
虽然我在按钮触发的两个函数里用global定义了这个变量:
def oneplayer(): title.configure(text = "One player") title.grid(column=3, row=0) global player_number player_number = "1" one_player.destroy() two_players.destroy() def twoplayers(): title.configure(text = "Two players") title.grid(column=3, row=0) global player_number player_number = "2" one_player.destroy() two_players.destroy()
完整代码如下:
import random from random import randint import tkinter as tk from tkinter import * window = tk.Tk() window.geometry("1400x860") window.title = "Rock paper scissors" result = Label(window, text= "result will appear here", bg="green") def oneplayer(): title.configure(text = "One player") title.grid(column=3, row=0) global player_number player_number = "1" one_player.destroy() two_players.destroy() def twoplayers(): title.configure(text = "Two players") title.grid(column=3, row=0) global player_number player_number = "2" one_player.destroy() two_players.destroy() one_player = Button(window, text = "One Player", command = oneplayer) two_players = Button(window, text= "Two players", command = twoplayers) title = Label(window, text = "Rock paper scissors" , bg= "blue", fg = "white", font= "Times") title.grid(column=3, row=0) def add_fillers(): filler = Label(window, text = " ") filler.grid(column=1, row=0) filler2 = Label(window, text = " ") filler2.grid(column=0, row=0) filler3 = Label(window, text = " ") filler3.grid(column=2, row=0) def choose_player_number(): one_player.grid(column= 2, row=1) two_players.grid(column= 4, row=1) computer_input = "" def computer_choice(): computer_input = randint("1", "2", "3") if computer_input == "1": computer_value = "Rock" elif computer_input == "2": computer_value = "paper" else: computer_value = "scissors" computer_result = Label(window, text= "the computer's choice was:" + computer_value) return computer_input def win(): result.configure(text= "You Win") def loose(): result.configure(text= "You loose") def draw(): result.configure(text= "Draw") def evaluate_rock(): computer_choice() if computer_input == "3": win() elif computer_input == "2": loose() elif computer_input == "1": draw() else: print ("error") rock = Button(window, text="Rock", command= evaluate_rock, fg="green", bg="blue") def run(): result.grid(column=3, row=1) if player_number == "1": rock.grid(column=2, row=2) add_fillers() choose_player_number() run() window.mainloop()
问题原因
- 程序启动时直接调用了
run(),此时用户还未点击任何选择按钮,player_number全局变量根本没被初始化,直接访问会报错。 run()函数内没有声明global player_number,即使后续用户点击按钮初始化了变量,函数也无法访问全局作用域的player_number。
解决步骤
- 全局初始化变量:在代码开头先定义
player_number的初始值,避免程序启动时的报错:player_number = "" - 在
run()中声明全局变量:修改run()函数,添加global声明:def run(): global player_number result.grid(column=3, row=1) if player_number == "1": rock.grid(column=2, row=2) - 调整
run()的调用时机:不要在程序启动时直接调用run(),而是放到oneplayer()和twoplayers()函数末尾,确保用户选择后再执行:def oneplayer(): title.configure(text = "One player") title.grid(column=3, row=0) global player_number player_number = "1" one_player.destroy() two_players.destroy() run() # 用户选择后再执行run逻辑 def twoplayers(): title.configure(text = "Two players") title.grid(column=3, row=0) global player_number player_number = "2" one_player.destroy() two_players.destroy() run() # 用户选择后再执行run逻辑 - 修复其他代码问题:
window.title应该用方法赋值:window.title("Rock paper scissors"),而不是直接赋值属性。computer_choice()中randint用法错误,应该传入整数范围randint(1,3),再转字符串:def computer_choice(): computer_num = randint(1,3) computer_input = str(computer_num) if computer_input == "1": computer_value = "Rock" elif computer_input == "2": computer_value = "paper" else: computer_value = "scissors" computer_result = Label(window, text= "the computer's choice was:" + computer_value) computer_result.grid() # 需要将标签布局到窗口 return computer_inputevaluate_rock()中需要接收computer_choice()的返回值:def evaluate_rock(): global computer_input computer_input = computer_choice() if computer_input == "3": win() elif computer_input == "2": loose() elif computer_input == "1": draw() else: print ("error")
修改后的完整代码
import random from random import randint import tkinter as tk from tkinter import * window = tk.Tk() window.geometry("1400x860") window.title("Rock paper scissors") # 修复title赋值方式 player_number = "" # 全局初始化变量 result = Label(window, text= "result will appear here", bg="green") def oneplayer(): title.configure(text = "One player") title.grid(column=3, row=0) global player_number player_number = "1" one_player.destroy() two_players.destroy() run() # 用户选择后执行run def twoplayers(): title.configure(text = "Two players") title.grid(column=3, row=0) global player_number player_number = "2" one_player.destroy() two_players.destroy() run() # 用户选择后执行run one_player = Button(window, text = "One Player", command = oneplayer) two_players = Button(window, text= "Two players", command = twoplayers) title = Label(window, text = "Rock paper scissors" , bg= "blue", fg = "white", font= "Times") title.grid(column=3, row=0) def add_fillers(): filler = Label(window, text = " ") filler.grid(column=1, row=0) filler2 = Label(window, text = " ") filler2.grid(column=0, row=0) filler3 = Label(window, text = " ") filler3.grid(column=2, row=0) def choose_player_number(): one_player.grid(column= 2, row=1) two_players.grid(column= 4, row=1) computer_input = "" def computer_choice(): computer_num = randint(1,3) # 修复randint用法 computer_input = str(computer_num) if computer_input == "1": computer_value = "Rock" elif computer_input == "2": computer_value = "paper" else: computer_value = "scissors" computer_result = Label(window, text= "the computer's choice was:" + computer_value) computer_result.grid(column=3, row=3) # 布局标签到窗口 return computer_input def win(): result.configure(text= "You Win") def loose(): result.configure(text= "You loose") def draw(): result.configure(text= "Draw") def evaluate_rock(): global computer_input computer_input = computer_choice() # 接收返回值 if computer_input == "3": win() elif computer_input == "2": loose() elif computer_input == "1": draw() else: print ("error") rock = Button(window, text="Rock", command= evaluate_rock, fg="green", bg="blue") def run(): global player_number result.grid(column=3, row=1) if player_number == "1": rock.grid(column=2, row=2) add_fillers() choose_player_number() # 移除启动时的run()调用 window.mainloop()
内容的提问来源于stack exchange,提问作者neo
相关产品推荐
相关产品推荐

