点击查看代码
import pygame
import sys
import random
import os
from pygame.locals import *
# 初始化pygame
pygame.init()
# 游戏常量
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
GRID_SIZE = 20
GRID_WIDTH = SCREEN_WIDTH // GRID_SIZE
GRID_HEIGHT = SCREEN_HEIGHT // GRID_SIZE
FPS = 10
# 方向常量
UP = (0, -1)
DOWN = (0, 1)
LEFT = (-1, 0)
RIGHT = (1, 0)
# 颜色定义
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 50, 50)
GREEN = (50, 255, 50)
BLUE = (50, 100, 255)
YELLOW = (255, 255, 50)
PURPLE = (180, 50, 230)
WALL_COLOR = (80, 80, 100)
BACKGROUND = (20, 20, 30)
TEXT_COLOR = (220, 220, 220)
HIGHLIGHT = (255, 200, 50)
# 随机蛇颜色
SNAKE_COLORS = [GREEN, BLUE, YELLOW, PURPLE]
class Snake:
def __init__(self):
self.reset()
# 随机选择蛇的颜色
self.color = random.choice(SNAKE_COLORS)
self.head_color = (
min(self.color[0] + 50, 255),
min(self.color[1] + 50, 255),
min(self.color[2] + 50, 255)
)
def reset(self):
# 蛇初始位置和长度
self.length = 3
self.positions = [(GRID_WIDTH // 2, GRID_HEIGHT // 2)]
self.direction = random.choice([UP, DOWN, LEFT, RIGHT])
self.score = 0
# 随机选择蛇的颜色
self.color = random.choice(SNAKE_COLORS)
self.head_color = (
min(self.color[0] + 50, 255),
min(self.color[1] + 50, 255),
min(self.color[2] + 50, 255)
)
def get_head_position(self):
return self.positions[0]
def update(self):
head = self.get_head_position()
x, y = self.direction
new_position = (((head[0] + x) % GRID_WIDTH), (head[1] + y) % GRID_HEIGHT)
# 检查是否撞墙
if (new_position[0] == 0 or new_position[0] == GRID_WIDTH - 1 or
new_position[1] == 0 or new_position[1] == GRID_HEIGHT - 1):
return False # 游戏结束
# 检查是否撞到自己
if new_position in self.positions[1:]:
return False # 游戏结束
self.positions.insert(0, new_position)
if len(self.positions) > self.length:
self.positions.pop()
return True
def draw(self, surface):
for i, p in enumerate(self.positions):
# 绘制蛇身
rect = pygame.Rect((p[0] * GRID_SIZE, p[1] * GRID_SIZE), (GRID_SIZE, GRID_SIZE))
if i == 0: # 蛇头
pygame.draw.rect(surface, self.head_color, rect)
pygame.draw.rect(surface, HIGHLIGHT, rect, 1)
else: # 蛇身
pygame.draw.rect(surface, self.color, rect)
pygame.draw.rect(surface, (self.color[0]//2, self.color[1]//2, self.color[2]//2), rect, 1)
class Apple:
def __init__(self):
self.position = (0, 0)
self.color = RED
self.randomize_position()
def randomize_position(self, snake_positions=None):
if snake_positions is None:
snake_positions = []
# 生成不在墙内和蛇身上的位置
while True:
self.position = (
random.randint(2, GRID_WIDTH - 3),
random.randint(2, GRID_HEIGHT - 3)
)
if self.position not in snake_positions:
break
def draw(self, surface):
rect = pygame.Rect((self.position[0] * GRID_SIZE, self.position[1] * GRID_SIZE), (GRID_SIZE, GRID_SIZE))
pygame.draw.rect(surface, self.color, rect)
pygame.draw.rect(surface, (255, 150, 150), rect, 2)
# 绘制苹果梗
pygame.draw.line(surface, (100, 50, 0),
(self.position[0] * GRID_SIZE + GRID_SIZE//2, self.position[1] * GRID_SIZE - 2),
(self.position[0] * GRID_SIZE + GRID_SIZE//2 - 3, self.position[1] * GRID_SIZE - 6), 2)
# 绘制苹果叶子
leaf_points = [
(self.position[0] * GRID_SIZE + GRID_SIZE//2, self.position[1] * GRID_SIZE - 5),
(self.position[0] * GRID_SIZE + GRID_SIZE//2 + 4, self.position[1] * GRID_SIZE - 8),
(self.position[0] * GRID_SIZE + GRID_SIZE//2 + 2, self.position[1] * GRID_SIZE - 10)
]
pygame.draw.polygon(surface, (50, 200, 50), leaf_points)
def draw_walls(surface):
# 绘制四周的墙
for x in range(GRID_WIDTH):
for y in range(GRID_HEIGHT):
if (x == 0 or x == GRID_WIDTH - 1 or y == 0 or y == GRID_HEIGHT - 1):
rect = pygame.Rect((x * GRID_SIZE, y * GRID_SIZE), (GRID_SIZE, GRID_SIZE))
pygame.draw.rect(surface, WALL_COLOR, rect)
pygame.draw.rect(surface, (60, 60, 80), rect, 1)
def draw_score(surface, score, high_score):
# 绘制分数面板
score_panel = pygame.Rect(SCREEN_WIDTH - 200, 10, 190, 70)
pygame.draw.rect(surface, (40, 40, 60), score_panel)
pygame.draw.rect(surface, (100, 100, 140), score_panel, 2)
# 绘制分数文本
font = pygame.font.SysFont('arial', 24, bold=True)
score_text = font.render(f'分数: {score}', True, TEXT_COLOR)
high_score_text = font.render(f'最高分: {high_score}', True, HIGHLIGHT)
surface.blit(score_text, (SCREEN_WIDTH - 180, 25))
surface.blit(high_score_text, (SCREEN_WIDTH - 180, 55))
def draw_game_over(surface, score):
# 绘制游戏结束面板
overlay = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT))
overlay.set_alpha(180)
overlay.fill((0, 0, 0))
surface.blit(overlay, (0, 0))
font_large = pygame.font.SysFont('arial', 72, bold=True)
font_medium = pygame.font.SysFont('arial', 36)
font_small = pygame.font.SysFont('arial', 24)
game_over_text = font_large.render('游戏结束!', True, RED)
score_text = font_medium.render(f'最终分数: {score}', True, HIGHLIGHT)
restart_text = font_small.render('按 R 键重新开始', True, TEXT_COLOR)
quit_text = font_small.render('按 ESC 键退出', True, TEXT_COLOR)
surface.blit(game_over_text, (SCREEN_WIDTH//2 - game_over_text.get_width()//2, SCREEN_HEIGHT//2 - 100))
surface.blit(score_text, (SCREEN_WIDTH//2 - score_text.get_width()//2, SCREEN_HEIGHT//2))
surface.blit(restart_text, (SCREEN_WIDTH//2 - restart_text.get_width()//2, SCREEN_HEIGHT//2 + 80))
surface.blit(quit_text, (SCREEN_WIDTH//2 - quit_text.get_width()//2, SCREEN_HEIGHT//2 + 120))
def main():
# 设置屏幕
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption('贪吃蛇游戏')
clock = pygame.time.Clock()
# 加载最高分
high_score = 0
if os.path.exists('high_score.txt'):
try:
with open('high_score.txt', 'r') as f:
high_score = int(f.read())
except:
pass
# 创建游戏对象
snake = Snake()
apple = Apple()
apple.randomize_position(snake.positions)
game_over = False
# 主游戏循环
while True:
for event in pygame.event.get():
if event.type == QUIT:
# 保存最高分
with open('high_score.txt', 'w') as f:
f.write(str(high_score))
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if game_over:
if event.key == K_r: # 重新开始
snake.reset()
apple.randomize_position(snake.positions)
game_over = False
elif event.key == K_ESCAPE: # 退出游戏
with open('high_score.txt', 'w') as f:
f.write(str(high_score))
pygame.quit()
sys.exit()
else:
# 方向控制
if event.key == K_UP and snake.direction != DOWN:
snake.direction = UP
elif event.key == K_DOWN and snake.direction != UP:
snake.direction = DOWN
elif event.key == K_LEFT and snake.direction != RIGHT:
snake.direction = LEFT
elif event.key == K_RIGHT and snake.direction != LEFT:
snake.direction = RIGHT
if not game_over:
# 更新蛇的位置
if not snake.update():
game_over = True
if snake.score > high_score:
high_score = snake.score
# 检查是否吃到苹果
if snake.get_head_position() == apple.position:
snake.length += 1
snake.score += 10
apple.randomize_position(snake.positions)
# 绘制背景
screen.fill(BACKGROUND)
# 绘制网格(背景)
for x in range(0, SCREEN_WIDTH, GRID_SIZE):
pygame.draw.line(screen, (30, 30, 40), (x, 0), (x, SCREEN_HEIGHT))
for y in range(0, SCREEN_HEIGHT, GRID_SIZE):
pygame.draw.line(screen, (30, 30, 40), (0, y), (SCREEN_WIDTH, y))
# 绘制墙
draw_walls(screen)
# 绘制苹果
apple.draw(screen)
# 绘制蛇
snake.draw(screen)
# 绘制分数
draw_score(screen, snake.score, high_score)
# 绘制游戏结束画面
if game_over:
draw_game_over(screen, snake.score)
pygame.display.update()
clock.tick(FPS)
if __name__ == "__main__":
main()