Tkinter剪刀石头布游戏:按钮点击后胜负与分数不更新
Tkinter剪刀石头布游戏:胜负与分数无法更新问题修复
问题描述
我用Tkinter开发剪刀石头布游戏,点击按钮后胜负结果和分数都没法更新。试过把move和cmove声明为全局变量,也试过在手势选择函数里定义,但都没用;不过游戏函数里显示敌方动作的代码是正常运行的。
原代码如下:
from tkinter import * from random import randint root = Tk() score = 0 scorel = Label(root, text= "Your score is: " + str(score) + "!") scorel.grid(row=0, column=1) move = "none" moves = ["Rock", "Paper", "Scissors"] def rock(): move = "Rock" return move def paper(): move = "Paper" return move def scissors(): move = "Scissors" return move cmove = "none" resultw = Label(root, text="No winners") resultw.grid(row=2, column=1) def game(): global score global clabel resultw.destroy() cmove = moves[randint(0, 2)] if move == cmove: resultw.config(text="It's a tie!") if move == "Rock": if cmove == "Scissors": resultw.config(text="You win!") score += 1 else: resultw.config(text="You lose!") score -= 1 if move == "Paper": if cmove == "Rock": resultw.config(text="You win!") score += 1 else: resultw.config(text="You lose!") score -= 1 if move == "Scissors": if cmove == "Paper": resultw.config(text="You win!") score += 1 else: resultw.config(text="You lose!") rockb = Button(root, text="Rock", command=lambda: [rock(), game()]) rockb.grid(row=3, column=0, ipadx=30, ipady=20) paperb = Button(root, text="Paper", command=lambda: [paper(), game()]) paperb.grid(row=3, column=1, ipadx=30, ipady=20) scissorsb = Button(root, text="Scissors", command=lambda: [scissors(), game()]) scissorsb.grid(row=3, column=2, ipadx=30, ipady=20) root.mainloop()
另外,原游戏函数中添加这段代码可正常显示敌方动作:
clabel = Label(root, text="Enemy move is: " + cmove + "!") clabel.grid(row=1, column=2)
问题根源
move变量未正确同步:手势选择函数里的move是局部变量,不会修改全局move;而且按钮的lambda调用函数后没把返回值赋值给全局move,导致全局move一直是初始的"none",胜负判断全走错误分支。- 控件销毁后无法更新:
game()里先销毁resultw,再调用config会直接报错,因为控件已经不存在了。 - 分数未同步到界面:即使
score变量变化了,scorel标签的文本没更新,界面上看不到分数变化。 cmove全局变量未声明:game()里的cmove是局部变量,逻辑上不严谨。
修复后的代码
from tkinter import * from random import randint root = Tk() score = 0 move = "none" moves = ["Rock", "Paper", "Scissors"] # 初始化分数标签 scorel = Label(root, text= "Your score is: " + str(score) + "!") scorel.grid(row=0, column=1) # 统一设置玩家手势的函数,直接修改全局move def set_move(new_move): global move move = new_move # 初始化结果标签 resultw = Label(root, text="No winners") resultw.grid(row=2, column=1) def game(): global score, move, cmove # 随机生成敌方手势 cmove = moves[randint(0, 2)] # 更新敌方手势标签:如果已创建就改文本,没创建就新建 try: clabel.config(text="Enemy move is: " + cmove + "!") except NameError: clabel = Label(root, text="Enemy move is: " + cmove + "!") clabel.grid(row=1, column=2) # 胜负判断逻辑,用elif减少冗余判断 if move == cmove: resultw.config(text="It's a tie!") elif move == "Rock": if cmove == "Scissors": resultw.config(text="You win!") score += 1 else: resultw.config(text="You lose!") score -= 1 elif move == "Paper": if cmove == "Rock": resultw.config(text="You win!") score += 1 else: resultw.config(text="You lose!") score -= 1 elif move == "Scissors": if cmove == "Paper": resultw.config(text="You win!") score += 1 else: resultw.config(text="You lose!") score -= 1 # 同步分数到界面 scorel.config(text= "Your score is: " + str(score) + "!") # 按钮逻辑:先设置手势,再执行游戏判断 rockb = Button(root, text="Rock", command=lambda: [set_move("Rock"), game()]) rockb.grid(row=3, column=0, ipadx=30, ipady=20) paperb = Button(root, text="Paper", command=lambda: [set_move("Paper"), game()]) paperb.grid(row=3, column=1, ipadx=30, ipady=20) scissorsb = Button(root, text="Scissors", command=lambda: [set_move("Scissors"), game()]) scissorsb.grid(row=3, column=2, ipadx=30, ipady=20) root.mainloop()
核心修改说明
- 合并手势选择函数为
set_move,直接修改全局move,避免局部变量的坑。 - 移除
resultw.destroy(),直接用config更新文本,控件可重复使用。 - 分数更新后立刻调用
scorel.config(),让界面同步显示最新分数。 - 敌方手势标签只创建一次,后续更新文本,避免界面上重复生成控件。
- 用
elif替代多个独立if,减少不必要的判断,逻辑更高效。
内容的提问来源于stack exchange,提问作者ravaldr
相关产品推荐
相关产品推荐

