在Pygame贪吃蛇项目中,如何实现蛇进食后增加身体段
贪吃蛇项目:实现进食后增加身体段的OOP方案建议
核心思路调整
当前你的Snake类仅维护了单个头部的位置,要实现身体增长,需要:
- 用列表存储蛇的所有身体段坐标,每段以
(x,y)形式保存 - 移动时头部先更新位置,后续身体段依次跟随前一段的旧位置
- 进食后在身体末尾追加一段坐标
- 替换距离检测为矩形碰撞,更精准判断蛇是否吃到食物
修改后的完整代码
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
相关产品推荐
相关产品推荐

