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

基于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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:39:51