基于Turtle Graphics的剪刀石头布游戏按键绑定失效问题
修复你的Turtle剪刀石头布游戏问题
嘿,我瞅见你在开发这个Turtle版的剪刀石头布时遇到了按键绑定报错和逻辑问题,这就帮你搞定!
首先说说你遇到的报错原因
你看到的TypeError: 'str' object is not callable,是因为在主循环里错误地使用了wn.onkeypress(rockfn(), 'r')——这里rockfn()会立刻执行并返回字符串Rock,但onkeypress需要的是函数对象(也就是不带括号的rockfn),当Tkinter尝试调用这个字符串时,自然就报错了。
除此之外,你的代码还有两个关键逻辑问题:
- 电脑的选择只在初始化时生成一次,玩家每一轮选的都是同一个电脑选择,这显然不符合游戏规则;
- 没有保存玩家的选择状态,每次判断时直接调用函数,无法正确记录玩家到底选了什么。
修复后的完整代码
import turtle import random # 创建屏幕 wn = turtle.Screen() wn.title('Rock Paper Scissors') wn.bgcolor('black') wn.setup(800, 600) wn.tracer(0) # 绘制石头、布、剪刀的图形 rock = turtle.Turtle() rock.shape('square') rock.goto(170, 100) rock.speed(0) rock.color('#964B00') rock.shapesize(stretch_wid=5, stretch_len=5) rock.penup() paper = turtle.Turtle() paper.shape('square') paper.goto(-170, 100) paper.speed(0) paper.color('white') paper.shapesize(stretch_wid=5, stretch_len=5) paper.penup() scissors = turtle.Turtle() scissors.shape('square') scissors.goto(0, -170) scissors.speed(0) scissors.color('blue') scissors.shapesize(stretch_wid=5, stretch_len=5) scissors.penup() # 顶部胜负显示文本 pen = turtle.Turtle() pen.speed(0) pen.color('white') pen.penup() pen.hideturtle() pen.goto(0, 240) pen.write("Who wins: ", align="center", font=("Courier", 24)) # 选项提示文本 pen1 = turtle.Turtle() pen1.speed(0) pen1.color('white') pen1.penup() pen1.hideturtle() pen1.goto(170, 152) pen1.write('Rock[R]', align="center", font=("Courier", 16)) pen2 = turtle.Turtle() pen2.speed(0) pen2.color('white') pen2.penup() pen2.hideturtle() pen2.goto(-168, 152) pen2.write('Paper[P]', align="center", font=("Courier", 16)) pen3 = turtle.Turtle() pen3.speed(0) pen3.color('white') pen3.penup() pen3.hideturtle() pen3.goto(0, -118) pen3.write('Scissors[S]', align="center", font=("Courier", 16)) # 全局变量保存玩家选择,初始为None player_choice = None # 更新玩家选择的回调函数 def choose_rock(): global player_choice player_choice = 'Rock' def choose_paper(): global player_choice player_choice = 'Paper' def choose_scissors(): global player_choice player_choice = 'Scissors' # 按键绑定(只需要初始化一次) wn.listen() wn.onkeypress(choose_rock, 'r') wn.onkeypress(choose_paper, 'p') wn.onkeypress(choose_scissors, 's') # 主游戏循环 while True: wn.update() # 当玩家做出选择时进行判断 if player_choice is not None: # 每轮重新生成电脑的选择 computer_choice = random.choice(['Rock', 'Paper', 'Scissors']) # 判断胜负 if player_choice == computer_choice: pen.clear() pen.write(f"It's a draw! Both chose {player_choice}", align="center", font=("Courier", 24)) elif (player_choice == 'Rock' and computer_choice == 'Scissors') or \ (player_choice == 'Paper' and computer_choice == 'Rock') or \ (player_choice == 'Scissors' and computer_choice == 'Paper'): pen.clear() pen.write(f"You win! Computer chose {computer_choice}", align="center", font=("Courier", 24)) else: pen.clear() pen.write(f"You lost! Computer chose {computer_choice}", align="center", font=("Courier", 24)) # 重置玩家选择,准备下一轮 player_choice = None
关键修改说明
- 新增全局变量
player_choice:用来记录玩家的选择状态,按键触发时更新这个变量,而不是让函数返回值; - 调整按键回调函数:让函数只负责更新
player_choice,不再返回字符串,符合Tkinter回调的要求; - 每轮重新生成电脑选择:确保玩家每次选择时,电脑都会随机选一个新的选项;
- 重构胜负判断逻辑:在主循环里检查
player_choice是否有值,然后和电脑选择比较,判断后重置player_choice,保证可以进行多轮游戏; - 移除循环内错误的
onkeypress调用:按键绑定只需要在初始化时设置一次,不需要在循环里重复执行。
内容的提问来源于stack exchange,提问作者octaviandd
相关产品推荐
相关产品推荐

