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

如何使用onkey退出turtle库中控制蛇移动的while循环?

Turtle贪吃蛇游戏:解决按键退出循环的错误

错误原因分析

你遇到的AttributeError: 'Turtle' object has no attribute 'done'是因为done()是turtle库中屏幕(Screen)对象或者模块级别的方法,不是Turtle实例(你的snake)的方法,所以调用snake.done()完全错误。

除此之外,原代码还有几个逻辑问题:

  • 嵌套的while True循环和turtle.mainloop()冲突,mainloop()本身就是事件循环,手动写的while True会阻塞事件处理,导致按键响应异常。
  • if window.onkey(exit,"e"):的写法无效,onkey()是用来注册按键触发的函数,不会返回布尔值,这种判断没有意义。
  • 在循环中重复注册按键事件是冗余操作,只需要注册一次即可。

修正方案

  1. 用window.bye()替代错误的snake.done(),bye()是Screen对象的方法,用来关闭窗口并结束程序。
  2. 使用turtle的ontimer()方法实现蛇的持续移动,避免手动写while True阻塞事件循环。
  3. 统一在初始化阶段注册所有按键事件,包括退出的'e'键。
  4. 设置全局变量控制蛇的移动状态,方便退出时终止移动循环。

修正后的完整代码

import turtle

# 初始化屏幕和蛇
window = turtle.Screen()
snake = turtle.Turtle()
snake.speed(0)
snake.penup()

# 全局标志:控制蛇是否继续移动
is_moving = False

def forward():
    global is_moving
    is_moving = True
    move_snake_continuously()

def move_snake_continuously():
    if is_moving:
        snake.forward(0.8)
        # 每隔10毫秒调用一次,实现非阻塞的持续移动
        window.ontimer(move_snake_continuously, 10)

def left():
    snake.left(90)

def right():
    snake.right(90)

def back():
    global is_moving
    is_moving = True
    snake.back(0.8)
    window.ontimer(lambda: snake.back(0.8) if is_moving else None, 10)

def exit_game():
    global is_moving
    is_moving = False
    window.bye()  # 关闭窗口,结束程序

# 一次性注册所有按键事件
window.listen()
window.onkey(forward, "w")
window.onkey(left, "a")
window.onkey(right, "d")
window.onkey(back, "s")
window.onkey(exit_game, "e")

# 启动turtle事件循环
window.mainloop()

代码说明

  • is_moving全局变量用来控制蛇的移动状态,按下'e'键时会将其设为False,终止后续的移动调用。
  • move_snake_continuously()通过ontimer()实现非阻塞的持续移动,不会影响按键事件的响应。
  • exit_game()函数负责停止移动并关闭窗口,彻底替代了原错误的snake.done()。
  • 所有按键事件仅注册一次,放在mainloop()之前,避免冗余操作。

内容的提问来源于stack exchange,提问作者Augustus

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 06:27:29