前四篇都在终端里玩文字游戏,这篇用 pygame 做经典贪吃蛇,首次接触"游戏主循环":每帧重复"处理输入 → 更新状态 → 绘制画面",理解了它,就理解了所有游戏引擎的工作方式。
玩法介绍
蛇由一串方块组成,方向键控制移动;吃到红色食物会变长并加分;撞墙或撞到自己则结束,速度随得分提升。窗口 480×480 像素,分 24×24 格,蛇和食物都按格子移动。
第 1 步:安装 pygame
pygame 是第三方库,先安装再验证:
pip install pygame
python3 -c "import pygame; print(pygame.version.ver)"
输出版本号即安装成功,下面所有代码保存到 snake.py 中运行。
第 2 步:窗口与主循环骨架
初始化 pygame,创建 480×480 窗口,写一个"空转"主循环:每帧填充背景、刷新画面、处理退出事件。这是所有 pygame 程序的基础骨架。
import pygame
W, H = 480, 480
CELL = 20
pygame.init()
screen = pygame.display.set_mode((W, H))
clock = pygame.time.Clock()
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
screen.fill((20, 20, 20))
pygame.display.flip()
clock.tick(10) # 每秒 10 帧,先慢一点
pygame.quit()
第 3 步:蛇与食物
蛇用"头部坐标 + 身体方块列表"表示,初始 3 格;食物是随机位置的方块。移动技巧:新头插入列表头部、尾部弹出;吃到食物时不弹尾,蛇就变长。
import random
GRID = W // CELL
snake = [(10, 10), (9, 10), (8, 10)] # 头在 (10,10),向右排
direction = (1, 0)
food = (random.randint(0, GRID-1), random.randint(0, GRID-1))
第 4 步:键盘控制与碰撞检测
监听 KEYDOWN 事件,按方向键改变 direction。注意防止"直接反向":蛇正在向右时不能按左,否则会撞死自己。
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP and direction != (0, 1):
direction = (0, -1)
elif event.key == pygame.K_DOWN and direction != (0, -1):
direction = (0, 1)
elif event.key == pygame.K_LEFT and direction != (1, 0):
direction = (-1, 0)
elif event.key == pygame.K_RIGHT and direction != (-1, 0):
direction = (1, 0)
每帧再按方向计算新头部:撞墙或撞到自己就结束;吃到食物则刷新食物,否则弹掉尾部。撞自己的检测放在插入头部之后,用 snake[1:] 判断。
head = (snake[0][0] + direction[0], snake[0][1] + direction[1])
if head[0] < 0 or head[0] >= GRID or head[1] < 0 or head[1] >= GRID:
print("撞墙了,游戏结束!")
break
snake.insert(0, head)
if head != food:
snake.pop()
第 5 步:绘制与完整代码
完整可运行版:蛇画成绿色、食物画成红色方块,标题栏实时显示分数,得分越高帧率越快。
import pygame, random
W = H = 480
CELL = 20
GRID = W // CELL
pygame.init()
screen = pygame.display.set_mode((W, H))
clock = pygame.time.Clock()
snake = [(10, 10), (9, 10), (8, 10)]
direction = (1, 0)
food = (random.randint(0, GRID-1), random.randint(0, GRID-1))
score = 0
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP and direction != (0, 1):
direction = (0, -1)
elif event.key == pygame.K_DOWN and direction != (0, -1):
direction = (0, 1)
elif event.key == pygame.K_LEFT and direction != (1, 0):
direction = (-1, 0)
elif event.key == pygame.K_RIGHT and direction != (-1, 0):
direction = (1, 0)
head = (snake[0][0] + direction[0], snake[0][1] + direction[1])
if head[0] < 0 or head[0] >= GRID or head[1] < 0 or head[1] >= GRID:
break
snake.insert(0, head)
if head == food:
score += 1
food = (random.randint(0, GRID-1), random.randint(0, GRID-1))
else:
snake.pop()
if head in snake[1:]:
break
screen.fill((20, 20, 20))
for x, y in snake:
pygame.draw.rect(screen, (0, 200, 80), (x*CELL, y*CELL, CELL-2, CELL-2))
pygame.draw.rect(screen, (220, 40, 40), (food[0]*CELL, food[1]*CELL, CELL-2, CELL-2))
pygame.display.set_caption(f"贪吃蛇 · 分数: {score}")
pygame.display.flip()
clock.tick(10 + score // 2)
pygame.quit()
print(f"游戏结束,得分: {score}")
第 6 步:运行与常见问题
保存为 snake.py,运行 python3 snake.py 即可游玩。常见问题:①窗口一闪而过,检查主循环缩进;②方向键没反应,确认焦点在游戏窗口;③太快或太卡,调整 clock.tick 参数(10~30 手感较好)。
💡 改进方向:①结束时显示"游戏结束"画面而不是直接退出;②食物不要生成在蛇身上;③给蛇头画眼睛、给身体加渐变色;④加入障碍物、加速道具,最高分写入文件持久化保存。