import pygame, sys, random
import pickle
from pygame.locals import *

初始化Pygame

pygame.init()
fpsClock = pygame.time.Clock()

设置窗口大小(放大比例)

SCALE_FACTOR = 2
WINDOW_WIDTH = 400 * SCALE_FACTOR
WINDOW_HEIGHT = 300 * SCALE_FACTOR
WINDOW = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT))
pygame.display.set_caption('greedy snake')

定义颜色

BLACK = pygame.Color(0, 0, 0)
WHITE = pygame.Color(255, 255, 255)
RED = pygame.Color(255, 0, 0)

蛇的初始位置和身体(按比例放大)

snake_position = [100 * SCALE_FACTOR, 50 * SCALE_FACTOR]
snake_body = [[100 * SCALE_FACTOR, 50 * SCALE_FACTOR],
[90 * SCALE_FACTOR, 50 * SCALE_FACTOR],
[80 * SCALE_FACTOR, 50 * SCALE_FACTOR]]

食物的初始位置(按比例放大)

food_position = [300 * SCALE_FACTOR, 150 * SCALE_FACTOR]
food_spawn = True
is_big_food = False # 是否是大食物
big_food_timer = 0 # 大食物计时器

蛇的初始方向

direction = 'RIGHT'
change_to = direction

初始化积分和最高历史记录

score = 0

字体设置(按比例放大)

font = pygame.font.Font(None, 36 * SCALE_FACTOR)
start_font = pygame.font.Font(None, 24 * SCALE_FACTOR) # 开始面板的字体大小

游戏状态

game_paused = False
game_over = False
game_started = False
show_scores = False # 是否显示成绩列表

初始化食物出现次数

food_count = 0

初始化难度和速度

difficulty = 'medium'
speed = 12

初始化最高历史记录

high_scores = {
'easy': 0,
'medium': 0,
'hard': 0
}

def load_high_scores():
try:
with open('high_scores.pkl', 'rb') as file:
return pickle.load(file)
except FileNotFoundError:
return {'easy': 0, 'medium': 0, 'hard': 0}
except Exception as e:
print(f"Error loading high scores: {e}")
return {'easy': 0, 'medium': 0, 'hard': 0}

def save_high_scores(high_scores):
with open('high_scores.pkl', 'wb') as file:
pickle.dump(high_scores, file)

def game_over_screen():
global high_scores, game_over
if score > high_scores[difficulty]:
high_scores[difficulty] = score
save_high_scores(high_scores)
game_over = True

def spawn_food():
global food_position, food_spawn, food_count, is_big_food, big_food_timer
while True:
food_position = [random.randint(0, 39) * 10 * SCALE_FACTOR,
random.randint(0, 29) * 10 * SCALE_FACTOR]
if food_position not in snake_body and food_position[1] < WINDOW_HEIGHT - 100 * SCALE_FACTOR:
break
food_spawn = True
food_count += 1
if score >= 10 and food_count % 5 == 0:
is_big_food = True
big_food_timer = pygame.time.get_ticks() # 重置大食物计时器
else:
is_big_food = False

def pause_game():
global game_paused
game_paused = not game_paused

def restart_game():
global snake_position, snake_body, food_position, food_spawn, direction, change_to, score, game_over, food_count, game_started, is_big_food, big_food_timer
snake_position = [100 * SCALE_FACTOR, 50 * SCALE_FACTOR]
snake_body = [[100 * SCALE_FACTOR, 50 * SCALE_FACTOR],
[90 * SCALE_FACTOR, 50 * SCALE_FACTOR],
[80 * SCALE_FACTOR, 50 * SCALE_FACTOR]]
food_position = [300 * SCALE_FACTOR, 150 * SCALE_FACTOR]
food_spawn = True
direction = 'RIGHT'
change_to = direction
score = 0
game_over = False
food_count = 0
game_started = False
is_big_food = False
big_food_timer = 0

def start_game(selected_difficulty):
global game_started, difficulty, speed
game_started = True
difficulty = selected_difficulty
if difficulty == 'easy':
speed = 8
elif difficulty == 'medium':
speed = 12
elif difficulty == 'hard':
speed = 16

初始化最高历史记录

high_scores = load_high_scores()

游戏主循环

while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == KEYDOWN:
if game_started:
if event.key == K_RIGHT or event.key == ord('d'):
change_to = 'RIGHT'
if event.key == K_LEFT or event.key == ord('a'):
change_to = 'LEFT'
if event.key == K_UP or event.key == ord('w'):
change_to = 'UP'
if event.key == K_DOWN or event.key == ord('s'):
change_to = 'DOWN'
if event.key == K_ESCAPE:
pygame.quit()
sys.exit()
if event.key == K_p:
pause_game()
if event.key == K_r:
restart_game()
else:
if event.key == ord('1'):
start_game('easy')
if event.key == ord('2'):
start_game('medium')
if event.key == ord('3'):
start_game('hard')
if event.key == ord('r'):
restart_game()
if event.key == ord('l'):
show_scores = True
if show_scores and event.key != ord('l'):
show_scores = False # 退出成绩列表界面

if game_started and not game_over:
    # 防止蛇直接反向移动
    if change_to == 'RIGHT' and not direction == 'LEFT':
        direction = 'RIGHT'
    if change_to == 'LEFT' and not direction == 'RIGHT':
        direction = 'LEFT'
    if change_to == 'UP' and not direction == 'DOWN':
        direction = 'UP'
    if change_to == 'DOWN' and not direction == 'UP':
        direction = 'DOWN'

    # 根据方向更新蛇头位置
    if not game_paused:
        if direction == 'RIGHT':
            snake_position[0] += 10 * SCALE_FACTOR
        if direction == 'LEFT':
            snake_position[0] -= 10 * SCALE_FACTOR
        if direction == 'UP':
            snake_position[1] -= 10 * SCALE_FACTOR
        if direction == 'DOWN':
            snake_position[1] += 10 * SCALE_FACTOR

        # 将蛇头的新位置插入到蛇身列表的开头
        snake_body.insert(0, list(snake_position))

        # 判断蛇是否吃到了食物
        if is_big_food:
            # 检测大食物的碰撞
            if (snake_position[0] in range(food_position[0], food_position[0] + 20 * SCALE_FACTOR) and
                snake_position[1] in range(food_position[1], food_position[1] + 20 * SCALE_FACTOR)):
                score += 5
                for _ in range(5):
                    snake_body.append(snake_body[-1])
                food_spawn = False
            else:
                snake_body.pop()
        else:
            # 检测普通食物的碰撞
            if snake_position[0] == food_position[0] and snake_position[1] == food_position[1]:
                score += 1
                food_spawn = False
            else:
                snake_body.pop()

        # 如果食物消失,生成新的食物
        if not food_spawn:
            spawn_food()

        # 检查大食物是否超时
        if is_big_food and pygame.time.get_ticks() - big_food_timer >= 20000:
            is_big_food = False
            food_spawn = False
            spawn_food()

    # 填充背景色
    WINDOW.fill(BLACK)

    # 绘制游戏区域
    game_area = pygame.Rect(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT - 100 * SCALE_FACTOR)
    pygame.draw.rect(WINDOW, WHITE, game_area, 1 * SCALE_FACTOR)

    # 绘制蛇身
    for pos in snake_body:
        pygame.draw.rect(WINDOW, RED, pygame.Rect(pos[0], pos[1], 10 * SCALE_FACTOR, 10 * SCALE_FACTOR))

    # 绘制食物
    if is_big_food:
        pygame.draw.rect(WINDOW, WHITE, pygame.Rect(food_position[0], food_position[1], 20 * SCALE_FACTOR, 20 * SCALE_FACTOR))
    else:
        pygame.draw.rect(WINDOW, WHITE, pygame.Rect(food_position[0], food_position[1], 10 * SCALE_FACTOR, 10 * SCALE_FACTOR))

    # 绘制积分显示区域
    score_area = pygame.Rect(0, WINDOW_HEIGHT - 100 * SCALE_FACTOR, WINDOW_WIDTH, 100 * SCALE_FACTOR)
    pygame.draw.rect(WINDOW, WHITE, score_area, 1 * SCALE_FACTOR)

    # 绘制积分
    score_text = font.render(f"Score: {score}", True, WHITE)
    WINDOW.blit(score_text, (10 * SCALE_FACTOR, WINDOW_HEIGHT - 80 * SCALE_FACTOR))

    # 绘制最高历史记录
    high_score_text = font.render(f"High Score ({difficulty}): {high_scores[difficulty]}", True, WHITE)
    WINDOW.blit(high_score_text, (10 * SCALE_FACTOR, WINDOW_HEIGHT - 40 * SCALE_FACTOR))

    # 判断蛇是否撞到了边界或自己的身体
    if not game_paused:
        if snake_position[0] >= WINDOW_WIDTH or snake_position[0] < 0:
            game_over_screen()
        if snake_position[1] >= WINDOW_HEIGHT - 100 * SCALE_FACTOR or snake_position[1] < 0:
            game_over_screen()
        for block in snake_body[1:]:
            if snake_position[0] == block[0] and snake_position[1] == block[1]:
                game_over_screen()

    # 绘制暂停或游戏结束界面
    if game_paused:
        overlay = pygame.Surface((WINDOW_WIDTH, WINDOW_HEIGHT))
        overlay.set_alpha(128)  # 设置透明度
        overlay.fill((0, 0, 0))  # 填充黑色
        WINDOW.blit(overlay, (0, 0))

        pause_text = font.render("stop", True, WHITE)
        WINDOW.blit(pause_text, (WINDOW_WIDTH // 2 - pause_text.get_width() // 2, WINDOW_HEIGHT // 2 - pause_text.get_height() // 2))
        resume_text = font.render("take R to continue", True, WHITE)
        WINDOW.blit(resume_text, (WINDOW_WIDTH // 2 - resume_text.get_width() // 2, WINDOW_HEIGHT // 2 + resume_text.get_height()))
elif game_over:
    # 绘制游戏结束界面
    WINDOW.fill(BLACK)
    game_over_text = font.render("game over", True, WHITE)
    WINDOW.blit(game_over_text, (WINDOW_WIDTH // 2 - game_over_text.get_width() // 2, WINDOW_HEIGHT // 2 - game_over_text.get_height() // 2))
    restart_text = font.render("take R to replay", True, WHITE)
    WINDOW.blit(restart_text, (WINDOW_WIDTH // 2 - restart_text.get_width() // 2, WINDOW_HEIGHT // 2 + restart_text.get_height()))
elif show_scores:
    # 绘制成绩列表界面
    WINDOW.fill(BLACK)
    title_text = font.render("High Scores", True, WHITE)
    WINDOW.blit(title_text, (WINDOW_WIDTH // 2 - title_text.get_width() // 2, 50 * SCALE_FACTOR))
    easy_score_text = font.render(f"Easy: {high_scores['easy']}", True, WHITE)
    WINDOW.blit(easy_score_text, (WINDOW_WIDTH // 2 - easy_score_text.get_width() // 2, 100 * SCALE_FACTOR))
    medium_score_text = font.render(f"Medium: {high_scores['medium']}", True, WHITE)
    WINDOW.blit(medium_score_text, (WINDOW_WIDTH // 2 - medium_score_text.get_width() // 2, 150 * SCALE_FACTOR))
    hard_score_text = font.render(f"Hard: {high_scores['hard']}", True, WHITE)
    WINDOW.blit(hard_score_text, (WINDOW_WIDTH // 2 - hard_score_text.get_width() // 2, 200 * SCALE_FACTOR))
    back_text = font.render("Press any key to go back", True, WHITE)
    WINDOW.blit(back_text, (WINDOW_WIDTH // 2 - back_text.get_width() // 2, 250 * SCALE_FACTOR))
else:
    # 绘制开始面板
    WINDOW.fill(BLACK)
    title_text = start_font.render("greedy snake", True, WHITE)
    WINDOW.blit(title_text, (WINDOW_WIDTH // 2 - title_text.get_width() // 2, 50 * SCALE_FACTOR))
    instruction_text = start_font.render("Choose difficulty: 1-Easy 2-Medium 3-Hard", True, WHITE)
    WINDOW.blit(instruction_text, (WINDOW_WIDTH // 2 - instruction_text.get_width() // 2, 100 * SCALE_FACTOR))
    list_text = start_font.render("Press L to view high scores", True, WHITE)
    WINDOW.blit(list_text, (WINDOW_WIDTH // 2 - list_text.get_width() // 2, 150 * SCALE_FACTOR))

# 动态调整游戏速度
if difficulty == 'easy':
    if score >= 50:
        speed = 10
    elif score >= 30:
        speed = 9
    elif score >= 10:
        speed = 8
elif difficulty == 'medium':
    if score >= 50:
        speed = 14
    elif score >= 30:
        speed = 13
    elif score >= 10:
        speed = 12
elif difficulty == 'hard':
    if score >= 50:
        speed = 18
    elif score >= 30:
        speed = 17
    elif score >= 10:
        speed = 16

# 控制游戏帧率
fpsClock.tick(speed)

# 更新屏幕显示
pygame.display.update()