150代码实现 Python 贪吃蛇 PyGame
·
1、效果展示



-
全中文界面:窗口标题、得分、结束提示全部中文化,不再是“tofu 块”。
-
动态加速:吃到食物越多,蛇移动越快,游戏节奏张弛有度。
-
智能转向:禁止 180° 掉头,操作更跟手。
2、如何运行
安装pygame
pip install pygame
复制下面代码, 保存为py文件,并允许
import pygame
import sys
import random
# 初始化 pygame
pygame.init()
# 常量设置
BLOCK_SIZE = 20 # 每一格方块的像素大小
GRID_WIDTH = 30 # 网格宽度(多少格)
GRID_HEIGHT = 20 # 网格高度(多少格)
WINDOW_WIDTH = GRID_WIDTH * BLOCK_SIZE
WINDOW_HEIGHT = GRID_HEIGHT * BLOCK_SIZE
# 颜色定义
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
GREEN = (0, 200, 0)
RED = (200, 0, 0)
DARK_GREEN = (0, 155, 0)
DARK_RED = (155, 0, 0)
# 创建窗口
screen = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT))
pygame.display.set_caption("贪吃蛇")
clock = pygame.time.Clock()
# 字体
def get_font(size):
"""尝试加载中文字体,若失败则退回默认字体"""
# 在 Windows 常见的中文字体列表
candidates = [
"Microsoft YaHei", # 微软雅黑
"SimHei", # 黑体
"SimSun", # 宋体
"NSimSun", # 新宋体
"FangSong", # 仿宋
"KaiTi", # 楷体
]
for name in candidates:
try:
font = pygame.font.SysFont(name, size)
# 检测字体是否真正支持中文:渲染一个汉字测试宽度
if font.render("测", True, (0, 0, 0)).get_width() > 0:
return font
except Exception:
continue
# 如果都失败,使用默认字体
return pygame.font.SysFont(None, size)
font_small = get_font(20)
font_large = get_font(48)
def draw_rect(color, position):
"""在给定位置绘制一个方块"""
rect = pygame.Rect(position[0], position[1], BLOCK_SIZE, BLOCK_SIZE)
pygame.draw.rect(screen, color, rect)
# ==== 方向与按键映射 ====
DXY = {'UP': (0, -BLOCK_SIZE), 'DOWN': (0, BLOCK_SIZE),
'LEFT': (-BLOCK_SIZE, 0), 'RIGHT': (BLOCK_SIZE, 0)}
OPPOSITE = {d: o for d, o in [('UP', 'DOWN'), ('DOWN', 'UP'), ('LEFT', 'RIGHT'), ('RIGHT', 'LEFT')]}
KEY_DIR = {k: d for keys, d in [((pygame.K_UP, pygame.K_w), 'UP'),
((pygame.K_DOWN, pygame.K_s), 'DOWN'),
((pygame.K_LEFT, pygame.K_a), 'LEFT'),
((pygame.K_RIGHT, pygame.K_d), 'RIGHT')] for k in keys}
def random_food(snake):
"""生成一个不与蛇身重叠的随机食物位置,使用海象运算符缩行"""
while (pos := [random.randint(0, GRID_WIDTH - 1) * BLOCK_SIZE,
random.randint(0, GRID_HEIGHT - 1) * BLOCK_SIZE]) in snake:
pass
return pos
def show_message(text, font, color, center):
"""在屏幕上居中显示文字"""
surface = font.render(text, True, color)
rect = surface.get_rect(center=center)
screen.blit(surface, rect)
def game_loop():
# 初始蛇身(居中开始,长度 3)
head_x = WINDOW_WIDTH // 2 // BLOCK_SIZE * BLOCK_SIZE
head_y = WINDOW_HEIGHT // 2 // BLOCK_SIZE * BLOCK_SIZE
snake = [[head_x - i * BLOCK_SIZE, head_y] for i in range(3)]
direction = change_to = 'RIGHT'
food = random_food(snake)
score = 0
while True:
# 事件处理
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit(); sys.exit()
if event.type == pygame.KEYDOWN:
if event.key in KEY_DIR:
change_to = KEY_DIR[event.key]
elif event.key == pygame.K_ESCAPE:
pygame.quit(); sys.exit()
# 更新方向(禁止直接掉头)
direction = change_to if change_to != OPPOSITE[direction] else direction
# 根据方向移动蛇头
dx, dy = DXY[direction]
head_x, head_y = head_x + dx, head_y + dy
snake.insert(0, [head_x, head_y]) # 新蛇头
# 碰撞检测:墙壁或自身
if not (0 <= head_x < WINDOW_WIDTH and 0 <= head_y < WINDOW_HEIGHT) or snake[0] in snake[1:]:
break
# 吃到食物
if snake[0] == food:
score += 1
food = random_food(snake)
else:
snake.pop()
# 绘制
screen.fill(BLACK)
draw_rect(RED, food)
for idx, pos in enumerate(snake):
draw_rect(DARK_GREEN if idx == 0 else GREEN, pos)
show_message("得分: " + str(score), font_small, WHITE, (60, 20))
pygame.display.flip()
clock.tick(10 + score // 5)
# 游戏结束画面
screen.fill(BLACK)
for i, txt in enumerate(("游戏结束", f"最终得分: {score}", "按任意键重新开始或 Esc 退出")):
show_message(txt, font_large if i == 0 else font_small, RED if i == 0 else WHITE,
(WINDOW_WIDTH // 2, WINDOW_HEIGHT // 2 - 40 + i * 45))
pygame.display.flip()
# 等待玩家操作
while (event := pygame.event.wait()).type not in (pygame.KEYDOWN, pygame.QUIT):
pass
if event.type == pygame.QUIT or (event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE):
pygame.quit(); sys.exit()
def main():
while True:
game_loop()
if __name__ == "__main__":
main()
更多推荐
所有评论(0)