[Python] 一个可识别窗口范围的贪吃蛇

import curses
import random
import time
import os

class SnakeGame:
    def __init__(self):
        # 初始化颜色
        self.init_colors()
        self.min_height = 10
        self.min_width = 30
        
        if not self.show_start_screen():
            raise SystemExit("游戏已取消")
            
        # 初始化游戏参数
        self.init_game()
    
    def init_colors(self):
        self.screen = curses.initscr()
        curses.start_color()
        curses.init_pair(1, curses.COLOR_GREEN, curses.COLOR_BLACK)   # 蛇的颜色
        curses.init_pair(2, curses.COLOR_RED, curses.COLOR_BLACK)     # 食物的颜色
        curses.init_pair(3, curses.COLOR_YELLOW, curses.COLOR_BLACK)  # 分数的颜色
        curses.init_pair(4, curses.COLOR_CYAN, curses.COLOR_BLACK)    # 提示文字颜色
    
    def show_start_screen(self):
        self.screen.clear()
        self.screen.keypad(1)
        curses.noecho()
        curses.curs_set(0)
        
        height, width = self.screen.getmaxyx()
        
        # 显示标题
        title = "贪吃蛇游戏"
        self.screen.addstr(height//4, (width-len(title))//2, title, curses.color_pair(3) | curses.A_BOLD)
        
        # 显示调整窗口提示
        instructions = [
            "请调整窗口大小至合适大小",
            f"最小要求: {self.min_width}x{self.min_height}",
            "当前大小: {}x{}",
            "",
            "按空格键开始游戏",
            "按 Q 退出游戏"
        ]
        
        while True:
            current_height, current_width = self.screen.getmaxyx()
            
            # 显示指示信息
            for i, text in enumerate(instructions):
                if "当前大小" in text:
                    text = text.format(current_width, current_height)
                y = height//4 + 2 + i
                if y < current_height - 1:  # 防止写入最后一行
                    self.screen.addstr(y, (width-len(text))//2, text, curses.color_pair(4))
            
            # 检查窗口大小是否合适
            size_ok = current_height >= self.min_height and current_width >= self.min_width
            status = "窗口大小合适 ✓" if size_ok else "窗口太小 ✗"
            status_color = curses.color_pair(1) if size_ok else curses.color_pair(2)
            self.screen.addstr(height//4 + len(instructions) + 1, 
                             (width-len(status))//2, 
                             status, 
                             status_color | curses.A_BOLD)
            
            self.screen.refresh()
            
            # 获取用户输入
            key = self.screen.getch()
            if key == ord(' ') and size_ok:  # 空格键且窗口大小合适
                return True
            elif key in (ord('q'), ord('Q')):  # Q键退出
                return False
            
            # 短暂延迟,降低CPU使用率
            time.sleep(0.1)
    
    def init_game(self):
        # 获取当前窗口大小
        self.height, self.width = self.screen.getmaxyx()
        self.screen.clear()
        self.screen.border(0)
        
        # 初始化蛇的位置(在屏幕中央)
        center_y = self.height // 2
        center_x = self.width // 2
        self.snake = [[center_y, center_x], 
                     [center_y, center_x-1], 
                     [center_y, center_x-2]]
        
        # 初始化其他游戏参数
        self.food = None
        self.generate_food()
        self.direction = curses.KEY_RIGHT
        self.score = 0
        self.speed = 0.1
        self.paused = False
        
    def generate_food(self):
        while True:
            self.food = [
                random.randint(1, self.height-2),
                random.randint(1, self.width-2)
            ]
            if self.food not in self.snake:
                break
    
    def show_score(self):
        score_text = f"分数: {self.score} | 按P暂停 | 按Q退出"
        self.screen.addstr(0, 2, score_text, curses.color_pair(3))
    
    def update_screen(self):
        self.screen.clear()
        self.screen.border(0)
        
        # 显示蛇
        for pos in self.snake:
            self.screen.addch(pos[0], pos[1], '#', curses.color_pair(1))
        
        # 显示食物
        self.screen.addch(self.food[0], self.food[1], '*', curses.color_pair(2))
        
        # 显示分数和控制说明
        self.show_score()
        
        # 如果游戏暂停,显示暂停信息
        if self.paused:
            pause_text = "游戏暂停中 - 按P继续"
            self.screen.addstr(self.height//2, (self.width-len(pause_text))//2, 
                             pause_text, curses.color_pair(4) | curses.A_BOLD)
        
        self.screen.refresh()
    
    def get_next_position(self):
        head = self.snake[0].copy()
        
        if self.direction == curses.KEY_UP:
            head[0] -= 1
        elif self.direction == curses.KEY_DOWN:
            head[0] += 1
        elif self.direction == curses.KEY_LEFT:
            head[1] -= 1
        elif self.direction == curses.KEY_RIGHT:
            head[1] += 1
            
        return head
    
    def play(self):
        while True:
            self.update_screen()
            
            # 获取用户输入
            self.screen.timeout(100)
            event = self.screen.getch()
            
            # 处理暂停
            if event in (ord('p'), ord('P')):
                self.paused = not self.paused
                continue
            
            # 处理退出
            if event in (ord('q'), ord('Q')):
                break
                
            # 如果游戏暂停,跳过其他处理
            if self.paused:
                continue
            
            # 更新方向
            if event in [curses.KEY_UP, curses.KEY_DOWN, curses.KEY_LEFT, curses.KEY_RIGHT]:
                # 防止蛇反向移动
                if (event == curses.KEY_UP and self.direction != curses.KEY_DOWN) or \
                   (event == curses.KEY_DOWN and self.direction != curses.KEY_UP) or \
                   (event == curses.KEY_LEFT and self.direction != curses.KEY_RIGHT) or \
                   (event == curses.KEY_RIGHT and self.direction != curses.KEY_LEFT):
                    self.direction = event
            
            # 计算蛇的下一个位置
            next_pos = self.get_next_position()
            
            # 检查是否撞墙
            if next_pos[0] in [0, self.height-1] or \
               next_pos[1] in [0, self.width-1] or \
               next_pos in self.snake[1:]:
                break
            
            # 移动蛇
            self.snake.insert(0, next_pos)
            
            # 检查是否吃到食物
            if next_pos == self.food:
                self.score += 10
                self.generate_food()
                # 加快游戏速度
                self.speed = max(0.05, self.speed * 0.95)
            else:
                self.snake.pop()
            
            time.sleep(self.speed)
    
    def end_game(self):
        curses.endwin()
        print(f"游戏结束!最终得分:{self.score}")

def main():
    try:
        game = SnakeGame()
        game.play()
        game.end_game()
    except SystemExit as e:
        curses.endwin()
        print(e)
    except Exception as e:
        curses.endwin()
        print(f"游戏发生错误:{e}")

if __name__ == "__main__":
    main()
posted @ 2025-02-20 09:57  夜歌乘年少  阅读(28)  评论(0)    收藏  举报