点击查看代码
import pygame
import sys
import random
pygame.init()
WIDTH, HEIGHT = 600, 500
GRID_SIZE = 20
GRID_WIDTH = WIDTH // GRID_SIZE
GRID_HEIGHT = HEIGHT // GRID_SIZE
FPS = 10
BACKGROUND = (15, 25, 35)
GRID_COLOR = (30, 45, 60)
SNAKE_HEAD = (0, 180, 0)
SNAKE_BODY = (0, 150, 0)
FOOD_COLOR = (220, 50, 50)
TEXT_COLOR = (200, 220, 240)
GAME_OVER_BG = (0, 0, 0, 180)
UP = (0, -1)
DOWN = (0, 1)
LEFT = (-1, 0)
RIGHT = (1, 0)
class Snake:
def __init__(self):
self.reset()
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.grow_to = 3
self.is_alive = True
def get_head_position(self):
return self.positions[0]
def update(self):
head = self.get_head_position()
x, y = self.direction
new_x = (head[0] + x) % GRID_WIDTH
new_y = (head[1] + y) % GRID_HEIGHT
new_position = (new_x, new_y)
if new_position in self.positions[1:]:
self.is_alive = False
return
self.positions.insert(0, new_position)
if len(self.positions) > self.grow_to:
self.positions.pop()
def render(self, surface):
for i, p in enumerate(self.positions):
rect = pygame.Rect((p[0] * GRID_SIZE, p[1] * GRID_SIZE), (GRID_SIZE, GRID_SIZE))
color = SNAKE_HEAD if i == 0 else SNAKE_BODY
pygame.draw.rect(surface, color, rect)
pygame.draw.rect(surface, (0, 100, 0), rect, 1)
def change_direction(self, direction):
if (direction[0] * -1, direction[1] * -1) == self.direction:
return
self.direction = direction
class Food:
def __init__(self):
self.position = (0, 0)
self.randomize_position()
def randomize_position(self):
self.position = (random.randint(0, GRID_WIDTH - 1),
random.randint(0, GRID_HEIGHT - 1))
def render(self, surface):
rect = pygame.Rect((self.position[0] * GRID_SIZE, self.position[1] * GRID_SIZE),
(GRID_SIZE, GRID_SIZE))
pygame.draw.rect(surface, FOOD_COLOR, rect)
pygame.draw.rect(surface, (180, 30, 30), rect, 1)
class Game:
def __init__(self):
self.screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("简易贪吃蛇游戏")
self.clock = pygame.time.Clock()
self.font = pygame.font.SysFont(None, 36)
self.small_font = pygame.font.SysFont(None, 24)
self.snake = Snake()
self.food = Food()
self.speed = FPS
def draw_grid(self):
for x in range(0, WIDTH, GRID_SIZE):
pygame.draw.line(self.screen, GRID_COLOR, (x, 0), (x, HEIGHT), 1)
for y in range(0, HEIGHT, GRID_SIZE):
pygame.draw.line(self.screen, GRID_COLOR, (0, y), (WIDTH, y), 1)
def draw_score(self):
score_text = self.font.render(f"得分: {self.snake.score}", True, TEXT_COLOR)
self.screen.blit(score_text, (10, 10))
length_text = self.small_font.render(f"长度: {len(self.snake.positions)}", True, TEXT_COLOR)
self.screen.blit(length_text, (10, 50))
speed_text = self.small_font.render(f"速度: {self.speed}", True, TEXT_COLOR)
self.screen.blit(speed_text, (10, 80))
def draw_game_over(self):
overlay = pygame.Surface((WIDTH, HEIGHT), pygame.SRCALPHA)
overlay.fill(GAME_OVER_BG)
self.screen.blit(overlay, (0, 0))
game_over_text = self.font.render("游戏结束!", True, (220, 50, 50))
restart_text = self.font.render("按 R 键重新开始", True, TEXT_COLOR)
quit_text = self.font.render("按 ESC 键退出", True, TEXT_COLOR)
score_text = self.font.render(f"最终得分: {self.snake.score}", True, TEXT_COLOR)
self.screen.blit(game_over_text, (WIDTH // 2 - game_over_text.get_width() // 2, HEIGHT // 2 - 80))
self.screen.blit(score_text, (WIDTH // 2 - score_text.get_width() // 2, HEIGHT // 2 - 30))
self.screen.blit(restart_text, (WIDTH // 2 - restart_text.get_width() // 2, HEIGHT // 2 + 20))
self.screen.blit(quit_text, (WIDTH // 2 - quit_text.get_width() // 2, HEIGHT // 2 + 70))
def draw_instructions(self):
text1 = self.small_font.render("方向键控制移动", True, (180, 200, 220))
text2 = self.small_font.render("P键暂停/继续", True, (180, 200, 220))
text3 = self.small_font.render("空格键加速", True, (180, 200, 220))
self.screen.blit(text1, (WIDTH - text1.get_width() - 10, 10))
self.screen.blit(text2, (WIDTH - text2.get_width() - 10, 40))
self.screen.blit(text3, (WIDTH - text3.get_width() - 10, 70))
def check_collision(self):
if self.snake.get_head_position() == self.food.position:
self.snake.grow_to += 1
self.snake.score += 10
self.food.randomize_position()
while self.food.position in self.snake.positions:
self.food.randomize_position()
if self.snake.score % 50 == 0:
self.speed = min(self.speed + 1, 20)
def run(self):
paused = False
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
pygame.quit()
sys.exit()
elif not self.snake.is_alive and event.key == pygame.K_r:
self.snake.reset()
self.food.randomize_position()
self.speed = FPS
elif self.snake.is_alive:
if event.key == pygame.K_UP:
self.snake.change_direction(UP)
elif event.key == pygame.K_DOWN:
self.snake.change_direction(DOWN)
elif event.key == pygame.K_LEFT:
self.snake.change_direction(LEFT)
elif event.key == pygame.K_RIGHT:
self.snake.change_direction(RIGHT)
elif event.key == pygame.K_p:
paused = not paused
elif event.key == pygame.K_SPACE:
self.speed = min(self.speed + 2, 20)
self.screen.fill(BACKGROUND)
self.draw_grid()
self.draw_score()
self.draw_instructions()
if self.snake.is_alive and not paused:
self.snake.update()
self.check_collision()
self.snake.render(self.screen)
self.food.render(self.screen)
if not self.snake.is_alive:
self.draw_game_over()
elif paused:
pause_text = self.font.render("游戏暂停", True, (220, 220, 100))
self.screen.blit(pause_text, (WIDTH // 2 - pause_text.get_width() // 2, HEIGHT // 2))
continue_text = self.small_font.render("按 P 键继续", True, TEXT_COLOR)
self.screen.blit(continue_text, (WIDTH // 2 - continue_text.get_width() // 2, HEIGHT // 2 + 50))
pygame.display.flip()
self.clock.tick(self.speed)
if __name__ == "__main__":
game = Game()
game.run()