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

在Pygame贪吃蛇项目中,如何实现蛇进食后增加身体段

贪吃蛇项目:实现进食后增加身体段的OOP方案建议

核心思路调整

当前你的Snake类仅维护了单个头部的位置,要实现身体增长,需要:

  1. 用列表存储蛇的所有身体段坐标,每段以(x,y)形式保存
  2. 移动时头部先更新位置,后续身体段依次跟随前一段的旧位置
  3. 进食后在身体末尾追加一段坐标
  4. 替换距离检测为矩形碰撞,更精准判断蛇是否吃到食物

修改后的完整代码

import pygame, random

pygame.init()

RED = (255,0,0)
GREEN = (0,255,0)
BLACK = (0,0,0)
WHITE = (255,255,255)

WINDOW_W = 800
WINDOW_H = 600
BACKGROUND_COLOR = BLACK
clock = pygame.time.Clock()

SNAKE_SIZE = 25
SNAKE_COLOR = GREEN
SNAKE_VEL = 25

FOOD_SIZE = SNAKE_SIZE
FOOD_COLOR = RED

FPS = 10

win = pygame.display.set_mode((WINDOW_W, WINDOW_H))
pygame.display.set_caption('G_G')

class Snake:
    def __init__(self, size, color, velocity, start_x, start_y):
        self.size = size
        self.color = color
        self.vel = velocity
        # 用列表存储身体段,初始有3段
        self.body = [(start_x, start_y), 
                     (start_x - size, start_y), 
                     (start_x - 2*size, start_y)]
        # 初始方向向右
        self.dx = velocity
        self.dy = 0

    def draw(self):
        # 遍历身体段绘制每一部分
        for segment in self.body:
            pygame.draw.rect(win, self.color, (segment[0], segment[1], self.size, self.size))

    def move(self):
        # 计算新头部位置
        head_x, head_y = self.body[0]
        new_head = (head_x + self.dx, head_y + self.dy)
        # 头部插入到列表最前面
        self.body.insert(0, new_head)
        # 默认移除最后一段(吃到食物时不移除)
        return self.body.pop()

    def grow(self, tail_pos):
        # 把刚才移除的尾部加回来,实现增长
        self.body.append(tail_pos)

    def wrap_around(self):
        # 处理穿墙逻辑,只需要更新头部位置
        head_x, head_y = self.body[0]
        if head_x < 0:
            self.body[0] = (WINDOW_W, head_y)
        elif head_x >= WINDOW_W:
            self.body[0] = (0 - self.size, head_y)
        if head_y < 0:
            self.body[0] = (head_x, WINDOW_H)
        elif head_y >= WINDOW_H:
            self.body[0] = (head_x, 0 - self.size)

class Food:
    def __init__(self, size, color):
        self.size = size
        self.color = color
        self.reset_pos()

    def reset_pos(self):
        # 生成在网格对齐的位置
        self.x = random.randrange(0, WINDOW_W, self.size)
        self.y = random.randrange(0, WINDOW_H, self.size)

    def draw(self):
        pygame.draw.rect(win, self.color, (self.x, self.y, self.size, self.size))

def check_collision(snake_head, food):
    # 矩形碰撞检测,比距离计算更准确
    return (snake_head[0] < food.x + food.size and
            snake_head[0] + snake.size > food.x and
            snake_head[1] < food.y + food.size and
            snake_head[1] + snake.size > food.y)

def draw_grid():
    for x in range(0, WINDOW_W + 1, SNAKE_SIZE):
        pygame.draw.line(win, WHITE, (x, 0), (x, WINDOW_H), 2)
    for y in range(0, WINDOW_H + 1, SNAKE_SIZE):
        pygame.draw.line(win, WHITE, (0, y), (WINDOW_W, y), 2)

def draw(snake, food):
    win.fill(BACKGROUND_COLOR)
    draw_grid()
    snake.draw()
    food.draw()
    pygame.display.update()

def main():
    run = True
    snake = Snake(SNAKE_SIZE, SNAKE_COLOR, SNAKE_VEL, 100, 100)
    food = Food(FOOD_SIZE, FOOD_COLOR)

    while run:
        clock.tick(FPS)
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False

        # 处理方向输入,添加方向锁避免反向移动
        keys = pygame.key.get_pressed()
        if keys[pygame.K_UP] and snake.dy == 0:
            snake.dx = 0
            snake.dy = -snake.vel
        if keys[pygame.K_DOWN] and snake.dy == 0:
            snake.dx = 0
            snake.dy = snake.vel
        if keys[pygame.K_RIGHT] and snake.dx == 0:
            snake.dx = snake.vel
            snake.dy = 0
        if keys[pygame.K_LEFT] and snake.dx == 0:
            snake.dx = -snake.vel
            snake.dy = 0

        # 移动蛇
        tail_pos = snake.move()
        snake.wrap_around()

        # 检测是否吃到食物
        if check_collision(snake.body[0], food):
            food.reset_pos()
            snake.grow(tail_pos)

        # 绘制画面
        draw(snake, food)

    pygame.quit()

if __name__ == "__main__":
    main()

关键修改说明

  • Snake类重构:用self.body列表存储所有身体段,move()方法处理头部移动和身体跟随逻辑,grow()方法通过恢复尾部位置实现身体增长
  • 方向控制优化:添加方向锁(比如向上时不能直接切换向下),避免蛇反向移动导致自撞
  • 碰撞检测改进:用矩形碰撞替代距离计算,判断蛇是否吃到食物的逻辑更准确
  • Food类调整:新增reset_pos()方法,规范重置食物位置的逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 18:45:59