import pygame import sys import random import time # 初始化 Pygame pygame.init() # 游戏常量 WIDTH, HEIGHT = 800, 600 GRID_SIZE = 20 GRID_WIDTH = WIDTH // GRID_SIZE GRID_HEIGHT = HEIGHT // GRID_SIZE FPS = 10 # 控制游戏速度 # 颜色定义 BACKGROUND = (15, 15, 30) GRID_COLOR = (30, 30, 60) SNAKE_HEAD = (50, 205, 50) # 蛇头颜色 - 浅绿色 SNAKE_BODY = (34, 139, 34) # 蛇身颜色 - 绿色 FOOD_COLOR = (220, 20, 60) # 食物颜色 - 红色 TEXT_COLOR = (220, 220, 220) SCORE_COLOR = (255, 215, 0) # 方向常量 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 = RIGHT self.score = 0 self.grow_to = 3 # 初始长度 self.is_alive = True # 初始添加蛇身 for i in range(1, self.length): self.positions.append((self.positions[0][0] - i, self.positions[0][1])) def get_head_position(self): """获取蛇头位置""" return self.positions[0] def turn(self, direction): """改变蛇的方向(不能直接反向)""" # 防止蛇直接反向移动 if (direction[0] * -1, direction[1] * -1) != self.direction: self.direction = direction def move(self): """移动蛇""" if not self.is_alive: return head = self.get_head_position() new_x = (head[0] + self.direction[0]) % GRID_WIDTH new_y = (head[1] + self.direction[1]) % 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 draw(self, surface): """绘制蛇""" for i, pos in enumerate(self.positions): # 蛇头用不同颜色 color = SNAKE_HEAD if i == 0 else SNAKE_BODY # 绘制蛇身矩形 rect = pygame.Rect( pos[0] * GRID_SIZE, pos[1] * GRID_SIZE, GRID_SIZE, GRID_SIZE ) pygame.draw.rect(surface, color, rect) pygame.draw.rect(surface, (color[0]//2, color[1]//2, color[2]//2), rect, 1) # 绘制蛇眼睛(头部) if i == 0: # 根据方向确定眼睛位置 eye_size = GRID_SIZE // 5 if self.direction == RIGHT: left_eye = (rect.right - eye_size*2, rect.top + eye_size*2) right_eye = (rect.right - eye_size*2, rect.bottom - eye_size*3) elif self.direction == LEFT: left_eye = (rect.left + eye_size, rect.top + eye_size*2) right_eye = (rect.left + eye_size, rect.bottom - eye_size*3) elif self.direction == UP: left_eye = (rect.left + eye_size*2, rect.top + eye_size) right_eye = (rect.right - eye_size*3, rect.top + eye_size) else: # DOWN left_eye = (rect.left + eye_size*2, rect.bottom - eye_size*2) right_eye = (rect.right - eye_size*3, rect.bottom - eye_size*2) pygame.draw.circle(surface, (255, 255, 255), left_eye, eye_size) pygame.draw.circle(surface, (255, 255, 255), right_eye, eye_size) pygame.draw.circle(surface, (0, 0, 0), left_eye, eye_size//2) pygame.draw.circle(surface, (0, 0, 0), right_eye, eye_size//2) def grow(self): """蛇生长""" self.grow_to += 1 self.score += 10 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 draw(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, border_radius=GRID_SIZE//3) # 添加一个小茎 stem_rect = pygame.Rect( rect.centerx - GRID_SIZE//10, rect.top - GRID_SIZE//4, GRID_SIZE//5, GRID_SIZE//4 ) pygame.draw.rect(surface, (139, 69, 19), stem_rect) # 添加一个高光 highlight = pygame.Rect( rect.left + GRID_SIZE//4, rect.top + GRID_SIZE//4, GRID_SIZE//4, GRID_SIZE//4 ) pygame.draw.ellipse(surface, (255, 100, 100), highlight) class Game: def __init__(self): self.screen = pygame.display.set_mode((WIDTH, HEIGHT)) pygame.display.set_caption("贪吃蛇游戏 - Python版") self.clock = pygame.time.Clock() self.font = pygame.font.SysFont('simhei', 25) self.big_font = pygame.font.SysFont('simhei', 50) self.snake = Snake() self.food = Food() self.speed = FPS self.game_over = False self.paused = False # 确保食物不在蛇身上 while self.food.position in self.snake.positions: self.food.randomize_position() def draw_grid(self): """绘制游戏网格""" for x in range(0, WIDTH, GRID_SIZE): pygame.draw.line(self.screen, GRID_COLOR, (x, 0), (x, HEIGHT)) for y in range(0, HEIGHT, GRID_SIZE): pygame.draw.line(self.screen, GRID_COLOR, (0, y), (WIDTH, y)) def draw_score(self): """绘制分数""" score_text = self.font.render(f"分数: {self.snake.score}", True, SCORE_COLOR) length_text = self.font.render(f"长度: {len(self.snake.positions)}", True, SCORE_COLOR) self.screen.blit(score_text, (10, 10)) self.screen.blit(length_text, (10, 40)) # 绘制操作说明 controls = [ "方向键: 控制移动", "空格键: 暂停/继续", "R键: 重新开始", "ESC键: 退出游戏" ] for i, text in enumerate(controls): control_text = self.font.render(text, True, TEXT_COLOR) self.screen.blit(control_text, (WIDTH - control_text.get_width() - 10, 10 + i * 30)) def draw_game_over(self): """绘制游戏结束画面""" game_over_surface = self.big_font.render("游戏结束!", True, (255, 50, 50)) score_surface = self.font.render(f"最终分数: {self.snake.score}", True, SCORE_COLOR) restart_surface = self.font.render("按R键重新开始,按ESC键退出", True, TEXT_COLOR) # 居中显示 self.screen.blit(game_over_surface, (WIDTH//2 - game_over_surface.get_width()//2, HEIGHT//2 - 60)) self.screen.blit(score_surface, (WIDTH//2 - score_surface.get_width()//2, HEIGHT//2)) self.screen.blit(restart_surface, (WIDTH//2 - restart_surface.get_width()//2, HEIGHT//2 + 50)) def draw_pause(self): """绘制暂停画面""" # 半透明覆盖层 overlay = pygame.Surface((WIDTH, HEIGHT), pygame.SRCALPHA) overlay.fill((0, 0, 0, 150)) self.screen.blit(overlay, (0, 0)) # 暂停文字 pause_surface = self.big_font.render("游戏暂停", True, (100, 200, 255)) continue_surface = self.font.render("按空格键继续游戏", True, TEXT_COLOR) self.screen.blit(pause_surface, (WIDTH//2 - pause_surface.get_width()//2, HEIGHT//2 - 40)) self.screen.blit(continue_surface, (WIDTH//2 - continue_surface.get_width()//2, HEIGHT//2 + 20)) def check_food_collision(self): """检查是否吃到食物""" if self.snake.get_head_position() == self.food.position: self.snake.grow() # 重新生成食物,确保不在蛇身上 while True: self.food.randomize_position() if self.food.position not in self.snake.positions: break # 每得100分增加一点速度 if self.snake.score % 100 == 0: self.speed = min(self.speed + 1, 20) # 最大速度限制 def handle_events(self): """处理游戏事件""" 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 event.key == pygame.K_r: # 重置游戏 self.__init__() elif event.key == pygame.K_SPACE: # 暂停/继续游戏 self.paused = not self.paused # 方向控制 if not self.paused and not self.game_over: if event.key == pygame.K_UP: self.snake.turn(UP) elif event.key == pygame.K_DOWN: self.snake.turn(DOWN) elif event.key == pygame.K_LEFT: self.snake.turn(LEFT) elif event.key == pygame.K_RIGHT: self.snake.turn(RIGHT) def run(self): """运行游戏主循环""" while True: self.handle_events() # 如果游戏暂停,只绘制界面不更新游戏状态 if self.paused: self.screen.fill(BACKGROUND) self.draw_grid() self.snake.draw(self.screen) self.food.draw(self.screen) self.draw_score() self.draw_pause() pygame.display.update() self.clock.tick(FPS) continue # 如果游戏结束,显示结束画面 if self.game_over: self.screen.fill(BACKGROUND) self.draw_grid() self.snake.draw(self.screen) self.food.draw(self.screen) self.draw_score() self.draw_game_over() pygame.display.update() self.clock.tick(FPS) continue # 更新游戏状态 self.snake.move() # 检查游戏是否结束 if not self.snake.is_alive: self.game_over = True # 检查是否吃到食物 self.check_food_collision() # 绘制游戏 self.screen.fill(BACKGROUND) self.draw_grid() self.snake.draw(self.screen) self.food.draw(self.screen) self.draw_score() # 如果游戏快结束了,闪烁提示 if not self.snake.is_alive: # 蛇死亡时的闪烁效果 if int(time.time() * 10) % 2 == 0: death_overlay = pygame.Surface((WIDTH, HEIGHT), pygame.SRCALPHA) death_overlay.fill((255, 50, 50, 50)) self.screen.blit(death_overlay, (0, 0)) pygame.display.update() self.clock.tick(self.speed) if __name__ == "__main__": # 检查是否安装了pygame try: game = Game() game.run() except pygame.error as e: print(f"错误: {e}") print("请确保已安装pygame库,可以使用以下命令安装:") print("pip install pygame") input("按回车键退出...")