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

使用turtle()实现的贪吃蛇游戏计数器异常递增问题修复

贪吃蛇计数器异常递增问题修复

问题现象

使用Python turtle库实现的贪吃蛇游戏,计数器偶尔会莫名递增2次,而非预期的每次吃食物递增1次。

问题根源

  1. move_snake被重复调度:reset()函数内直接调用了move_snake(),同时代码末尾又通过turtle.ontimer(move_snake, delay)启动调度,导致同一时间段内move_snake被多次执行,单次吃食物操作可能被重复检测。
  2. 碰撞检测阈值过大:当前用get_distance(new_head, food_position) < 20判断碰撞,蛇头方块尺寸为20x20、食物为10x10,实际碰撞阈值应为两者半宽之和15,阈值过大会导致蛇头移动过程中连续多帧被判定为碰撞。
  3. 重复调用画面更新:update_food_collision_count()和update_snake_on_screen()均调用了screen.update(),可能导致画面更新与逻辑执行不同步,间接引发计数异常。

修改方案

  • 移除reset()内的move_snake()调用,仅保留代码末尾的turtle.ontimer(move_snake, delay)启动游戏循环,避免重复调度。
  • 将碰撞检测的距离阈值从20调整为15,匹配实际物体尺寸,避免重复触发碰撞判定。
  • 删除update_food_collision_count()中的screen.update(),由update_snake_on_screen()统一负责画面更新,保证逻辑与画面同步。

修改后的完整代码

import turtle
import random

w = 500
h = 500
food_size = 10
delay = 100

offsets = {
    "up": (0, 20),
    "down": (0, -20),
    "left": (-20, 0),
    "right": (20, 0)
}

def reset():
    global snake, snake_dir, food_position, pen, food_collision_count
    snake = [[-180, 30], [-180, 50], [-180, 70], [-180, 90], [-180, 110]]
    snake_dir = "up"
    food_position = get_random_food_position()
    food.goto(food_position)
    food_collision_count = 0

def move_snake():
    global snake_dir, pen, food_position, food_collision_count

    new_head = snake[-1].copy()
    new_head[0] += offsets[snake_dir][0]
    new_head[1] += offsets[snake_dir][1]

    for i in range(2):
        if new_head[i] > w / 2:
            new_head[i] -= w
        elif new_head[i] < -w / 2:
            new_head[i] += w

    if new_head in snake[:-1]:
        reset()
        return

    snake.append(new_head)

    x = 0

    # 调整碰撞检测阈值为15
    if get_distance(new_head, food_position) < 15:
        food_collision_count = food_collision_count + 1
        update_food_collision_count()
        food_position = get_random_food_position()
        food.goto(food_position)
        x += food_collision_count
    else:
        snake.pop(0)
    high_score = x

    update_snake_on_screen()

    turtle.ontimer(move_snake, delay)

def update_snake_on_screen():
    pen.clearstamps()
    for segment in snake:
        pen.goto(segment[0], segment[1])
        pen.stamp()
    screen.update()

def update_food_collision_count():
    pen_count.clear()
    pen_count.goto(0, h / 2 - 20)
    pen_count.write(f"Food Collision Count: {food_collision_count}", align="center", font=("Arial", 12, "normal"))

def get_random_food_position():
    x = random.randint(-w / 2 + food_size, w / 2 - food_size)
    y = random.randint(-h / 2 + food_size, h / 2 - food_size)
    return (x, y)

def get_distance(pos1, pos2):
    x1, y1 = pos1
    x2, y2 = pos2
    distance = ((y2 - y1) ** 2 + (x2 - x1) ** 2) ** 0.5
    return distance

def update_direction(new_direction):
    global snake_dir, current_direction
    if snake_dir != opposite_direction(current_direction):
        snake_dir = new_direction

def change_direction(direction):
    global snake_dir, current_direction

    current_direction = snake_dir

    switch = {
        "up": lambda: update_direction("up"),
        "right": lambda: update_direction("right"),
        "down": lambda: update_direction("down"),
        "left": lambda: update_direction("left"),
    }

    switch.get(direction, lambda: None)()

def opposite_direction(current_direction):
    opposites = {"up": "down", "down": "up", "left": "right", "right": "left"}
    return opposites.get(current_direction, current_direction)

def handle_direction_key(direction):
    switch = {
        "Up": "up",
        "Right": "right",
        "Down": "down",
        "Left": "left",
    }

    change_direction(switch.get(direction, ""))

screen = turtle.Screen()
screen.setup(w, h)
screen.title("Snake")
screen.bgcolor("blue")
screen.tracer(0)

pen = turtle.Turtle("square")
pen.penup()

pen_count = turtle.Turtle()
pen_count.hideturtle()
pen_count.penup()

food = turtle.Turtle()
food.shape("square")
food.color("yellow")
food.shapesize(food_size / 20)
food.penup()

screen.listen()
screen.onkey(lambda: handle_direction_key("Up"), "Up")
screen.onkey(lambda: handle_direction_key("Right"), "Right")
screen.onkey(lambda: handle_direction_key("Down"), "Down")
screen.onkey(lambda: handle_direction_key("Left"), "Left")

reset()

turtle.ontimer(move_snake, delay)

turtle.done() 

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 13:07:04