1、效果展示

  1. 全中文界面:窗口标题、得分、结束提示全部中文化,不再是“tofu 块”。

  2. 动态加速:吃到食物越多,蛇移动越快,游戏节奏张弛有度。

  3. 智能转向:禁止 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()
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐