使用turtle()实现的贪吃蛇游戏计数器异常递增问题修复
贪吃蛇计数器异常递增问题修复
问题现象
使用Python turtle库实现的贪吃蛇游戏,计数器偶尔会莫名递增2次,而非预期的每次吃食物递增1次。
问题根源
- move_snake被重复调度:
reset()函数内直接调用了move_snake(),同时代码末尾又通过turtle.ontimer(move_snake, delay)启动调度,导致同一时间段内move_snake被多次执行,单次吃食物操作可能被重复检测。 - 碰撞检测阈值过大:当前用
get_distance(new_head, food_position) < 20判断碰撞,蛇头方块尺寸为20x20、食物为10x10,实际碰撞阈值应为两者半宽之和15,阈值过大会导致蛇头移动过程中连续多帧被判定为碰撞。 - 重复调用画面更新:
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
相关产品推荐
相关产品推荐

