声明:本文为GPT生成,注意辨别(没时间懒得写,基本都是废话,最后是完整代码)
作者:陆炳阳(Vincent Cassano)
版本:v1.0.5(最终版本)
项目地址:https://github.com/VincentCassano/SnakeAI_Game


一、项目背景与目标

传统的贪吃蛇游戏在算法与图形交互上具有良好的教学价值,但长期停留于手动操作与静态规则,缺乏智能化与系统复杂性。本项目的设计目标,是在经典贪吃蛇基础上引入人工智能控制逻辑多模式结构体系,构建一个既具游戏性又具算法研究意义的完整系统框架。

该项目不仅是一个娱乐性程序,更是一套用于算法实验、路径规划研究与人机博弈分析的轻量级仿真平台。


二、系统概述

系统由单一主类 SnakeGame 构成,基于 Python + Pygame 实现。核心架构遵循模块化设计原则,将逻辑、渲染、声音、交互分别封装为可独立调用的函数。

程序运行环境:

  • Python 3.8 及以上版本

  • 依赖库:pygame, numpy

  • 运行方式:

    python snakeAI_Game-v1.0.5.py
    

三、功能模块设计

(一)多模式系统

系统支持三种独立运行模式,分别对应不同的游戏与算法实验需求:

模式

功能描述

研究意义

普通模式

玩家手动控制蛇,规则与传统贪吃蛇一致

用于人类操作基线数据采集

对抗模式

玩家与AI蛇同时存在,互为敌手,碰撞即死亡

用于博弈算法验证与AI行为分析

影子模式(三蛇模式)

玩家控制主蛇,两条AI蛇镜像模仿其动作,任何AI死亡均导致失败

用于群体同步、镜像行为仿真

三种模式共享统一的逻辑基础,通过差异化的初始化(reset_*)和执行逻辑(step_*)实现模式切换。


(二)AI控制与对抗逻辑

AI蛇通过方向更新与位置集合动态维护实现半自主行为控制。主要逻辑包括:

  1. 碰撞检测机制
    使用 set 结构进行O(1)级别的空间冲突检测;

  2. 环境状态维护
    通过 non_snake 集合记录可用空间,用于路径规划与食物生成;

  3. 状态重置与重部署
    在AI死亡后自动调用 respawn_opponent() 进行重生,确保博弈过程持续;

  4. 奖励与惩罚机制
    玩家击败对抗蛇获得额外分值,用于后续AI学习策略的量化。

该结构为未来引入**强化学习(Reinforcement Learning)启发式路径搜索(如A*)**算法奠定了可扩展接口。


(三)图形界面与交互设计

图形系统使用Pygame底层API实现,特点如下:

  • 渲染层次清晰:背景、棋盘、蛇体、食物分层绘制;

  • 动态效果增强:食物具备脉动特效与高光反射,吃食物后触发短时光晕反馈;

  • 视觉语义清晰:不同类型蛇体采用不同配色(玩家蓝、AI红/紫),方向以眼睛方位标识;

  • 容错与兼容性设计:中文字体自动匹配(SimHei微软雅黑等),音效加载失败时程序不崩溃。

界面视觉风格克制而非花哨,重点在于可视化信息表达的清晰与稳定。


(四)音效系统与静默容错机制

系统音效模块基于 pygame.mixer 实现,包含以下部分:

  • 背景音乐循环控制;

  • 吃食物、死亡、倒计时三类短音效;

  • 音量动态调节与错误静默机制。

若运行环境不支持音频输出或文件缺失,程序通过异常捕获自动降级为“静音模式”,确保游戏逻辑不受影响。


四、程序结构

下图展示了系统的核心逻辑流程(伪图式描述):

初始化游戏环境
│
├── 模式选择 (普通 / 对抗 / 影子)
│
├── 状态重置 reset_*()
│
├── 主循环:
│   ├── 接收玩家输入
│   ├── 更新AI决策(若存在)
│   ├── 检测碰撞与死亡条件
│   ├── 生成或更新食物位置
│   ├── 绘制场景(draw_*)
│   ├── 更新分数与状态
│   └── 音效触发与渲染刷新
│
└── 游戏结束处理与重启选项

这种循环设计使逻辑流畅、易于扩展,可直接嵌入深度强化学习训练框架中进行状态-动作反馈研究。


五、程序工程特征

  1. 封装性强:类结构统一,函数粒度合理,便于集成与扩展;

  2. 鲁棒性设计:各模块均包含异常处理逻辑,保障系统稳定;

  3. 数据可视化基础:图形渲染可输出状态图像帧,为AI训练数据采集提供基础;

  4. 算法接口开放step() 函数返回状态字典,可直接对接强化学习模型。


六、结论

本项目在传统贪吃蛇的基础上完成了多模式设计、AI参与机制、图形与音效增强、工程化结构重构
版本 v1.0.5 为最终迭代版本,代码稳定、注释完善,可作为教学实验代码库AI算法测试平台长期维护使用。

本系统的实现验证了人工智能与交互式游戏结合的可行路径,也为“轻量化仿真环境”提供了一个可复现的样本。

技术的严肃性,不在于复杂度,而在于结构的自洽与目的的清晰。

七、完整代码

# 文件名: snakeAI_Game-v1.0.5.py
# 贪吃蛇游戏主程序
# 运行: python snakeAI_Game-v1.0.5.py
"""
                                                  #    %:%                                                              
                                                  -=%  #.-#                                                             
                                                  :..+ #...*                                                            
                                                  *...-*....:%                                                          
                                                  #...........*                                                         
                                                   -...........-+                                                       
                                                   +.............-*%                                                    
                                                   %-...............=#                                                  
                                                    +.................-*%                                               
                                                     :...................=%                                             
                                                     #.....................*                                            
                                                      =.....................:++##%%                                     
                                                      %.............................-:*+%                               
                                                      =...................................:*#                           
                                                   #=-.......................................-=#                        
                                                #=-.............................................-*%                     
                                             %*-..........................................-=****==:=%                   
                                           %*-.............................................-*%      %                   
                                          +-..................................................=#                        
                                        %:......................................................:#                      
                                       #-.........................................................=%                    
                                      #............................................................-+                   
                                     %-..........:*=.................................................=                  
                                     :........:*% #...................................................:%                
                                    =......:*%    :....................................................-%               
                                  #-....:*%     %:......................................................-%              
                                #:.....==::::::-.........................................................:              
                             %+-.................................................................-:.......*             
                           #=.....................................................................*%+=.....%            
                        +=-........................................................................*  %=...=            
                    %+:.....................::......................................................+   %:..%           
                %+=-....................-:..# *.....................................................-%    *.+           
            +*:-.....................:..* %#   =.....................................................=     +=           
            =.......................- %+#  %=*#:......................................................%     %           
             *...................:%++    % %..........................................................=                 
              #:.............:==-.%  %  #.-:..........................................................-                 
                #=.........+     %%  =-==...........----...............................................%                
                   #*..-++=%%     *=+=........:*+#%      %#*-..........................................#                
                     #-.%   -=#   =.......-*#                =.........................................#                
                       #+   %-.---......:#                    :...............................-:.......#                
                            %-........=%                      +................................%*......%                
                             %*-....:#                        +................................+ #....-                 
                                %##%                          =.::.............................+  +...=                 
                                                             #.:%=.............................+   =..#                 
                                                            %-*  :.............................+   %.:                  
                                                           #*%   -.............................%    :#                  
                                                                #.....................-.......-     %                   
                                                                =....................=#.......*                         
                                                               %.....................# =.....-%                         
                                                               :....................=  %.....+                          
                                                              *....................:    -...:                           
                                                             +.......=-...........-%    :..-%                           
                                                            *......-#%...........-%     -.-%                            
                                                          %=.....-*  *..........:%     %.-%                             
                                                         +-....-*%  %..........*       #:%                              
                                                       %:....:+     :........:%        %                                
                                                     #=...:*%      =.......:#                                           
                                                   +:.-=+%       %:......=#                                             
                                                %#*+#           +-....:+%                                               
                                                              #:..-=+%                                                  
                                                            +=:=+%                                                      
项目版本:v1.0.5 此版本为该项目最终迭代版本,暂无更新的计划
程序制作人: 陆炳阳(Vincent Cassano)
"""

# 导入必要的模块
import sys, random, heapq, time, pygame
from pygame import mixer
import numpy as np
from collections import deque, defaultdict
# ---------------------------
# 游戏主类
# ---------------------------
class SnakeGame:
    # 游戏主类
    def __init__(self, seed=0, board_size=50, silent_mode=False):
        """
        初始化贪吃蛇游戏
        
        参数:
            seed: 随机种子,用于复现游戏状态
            board_size: 棋盘边长(格子数)
            silent_mode: True 时不初始化 pygame 显示(便于无界面测试)
        """
        # 随机数设置
        random.seed(seed)
        
        # 游戏配置参数
        self.board_size = board_size    # 棋盘边长(格子数)
        self.cell_size = 20            # 每个格子的像素大小
        self.border_size = 40          # 边框大小
        
        # 计算尺寸相关变量
        self.width = self.board_size * self.cell_size  # 棋盘宽度
        self.height = self.width                       # 棋盘高度(正方形)
        self.grid_size = self.board_size ** 2          # 总格子数
        
        # 显示窗口尺寸
        self.display_width = 1080  # 固定窗口宽度
        self.display_height = 860  # 固定窗口高度
        
        # 游戏状态初始化
        self.silent_mode = silent_mode
        
        # 初始化显示和音频
        if not silent_mode:
            pygame.init()
            pygame.display.set_caption("贪吃蛇游戏 - 多模式AI版本")
            self.screen = pygame.display.set_mode((self.display_width, self.display_height))
            # 加载图标
            try:
                icon = pygame.image.load("./icon.png")
                pygame.display.set_icon(icon)
            except pygame.error as e:
                print("图标加载失败:", e)

            # 使用字体列表,确保中文字体能正确加载
            chinese_fonts = ["SimHei", "WenQuanYi Micro Hei", "Heiti TC", "Arial Unicode MS", "Microsoft YaHei"]
            self.font = pygame.font.SysFont(chinese_fonts, 24)
            self.large_font = pygame.font.SysFont(chinese_fonts, 30)

            # 尝试加载声音文件(静默失败)
            try:
                mixer.init()
                # 设置默认音量
                mixer.music.set_volume(0.3)  # 背景音乐音量30%
                
                # 加载音效
                self.sound_eat = mixer.Sound("sound/eat.wav")
                self.sound_game_over = mixer.Sound("sound/game_over.wav")
                self.sound_count = mixer.Sound("sound/count.wav")
                
                # 设置音效音量
                if self.sound_eat:
                    self.sound_eat.set_volume(0.6)  # 吃食物音效音量60%
                if self.sound_game_over:
                    self.sound_game_over.set_volume(0.8)  # 游戏结束音效音量80%
                if self.sound_count:
                    self.sound_count.set_volume(0.5)  # 倒计时音效音量50%
                
                # 初始化背景音乐状态
                self.bgm_playing = False
                    
            except Exception as e:
                # 记录错误但继续运行
                print(f"音效初始化失败: {e}")
                self.sound_eat = None
                self.sound_game_over = None
                self.sound_count = None
                self.bgm_playing = False
        else:
            self.screen = None
            self.font = None
            self.large_font = None
            self.sound_eat = None
            self.sound_game_over = None
            self.sound_count = None
            
        # 游戏速度设置
        self.speed = 30  # 默认游戏速度

        self.snake = None
        self.non_snake = None
        self.direction = None
        self.score = 0
        self.food = None
        self.seed_value = seed
        random.seed(seed)  # 设置随机种子
        np.random.seed(seed)
        
        # 背景音乐控制标志
        self.bgm_enabled = True  # 默认启用背景音乐

        self.reset()


    # ---------------------------
    # 音乐设置
    # ---------------------------

    # 播放背景音乐
    def play_bgm(self):
        """播放背景音乐
        
        尝试播放背景音乐,如果文件不存在则静默失败。
        """
        if self.bgm_enabled and not self.bgm_playing:
            try:
                # 尝试加载并播放背景音乐(循环播放)
                mixer.music.load("sound/victory.wav")  # 使用现有的victory.wav作为背景音乐
                mixer.music.play(-1)  # -1表示循环播放
                self.bgm_playing = True
            except Exception:
                # 如果背景音乐文件不存在或无法播放,静默失败
                pass
    
    # 暂停背景音乐
    def pause_bgm(self):
        """暂停背景音乐"""
        if self.bgm_playing:
            try:
                mixer.music.pause()
                self.bgm_playing = False
            except Exception:
                pass
    
    # 恢复播放背景音乐
    def resume_bgm(self):
        """恢复播放背景音乐"""
        if self.bgm_enabled and not self.bgm_playing:
            try:
                mixer.music.unpause()
                self.bgm_playing = True
            except Exception:
                pass
    
    # 停止背景音乐
    def stop_bgm(self):
        """停止背景音乐"""
        if self.bgm_playing:
            try:
                mixer.music.stop()
                self.bgm_playing = False
            except Exception:
                pass
    

    # ---------------------------
    # 重置游戏状态
    # ---------------------------

    # 重置游戏状态(普通模式)
    def reset(self):
        """重置游戏状态(普通模式)
        
        初始化玩家蛇、食物位置和游戏状态变量。
        """
        # 计算棋盘中心点
        mid = self.board_size // 2
        
        # 初始化玩家蛇(3节,位于中心)
        self.snake = [(mid + i, mid) for i in range(1, -2, -1)]
        self.snake_set = set(self.snake)  # 用于快速碰撞检测
        self.direction = "DOWN"          # 玩家蛇初始方向
        
        # 初始化游戏状态
        self.score = 0
        self.death_reason = None
        self.game_start_time = time.time()  # 初始化游戏开始时间
        
        # 更新可用位置集合
        self._update_available_positions()
        
        # 生成初始食物
        self.food = self._generate_food()
    
    # 重置游戏状态(影子模式)
    def reset_three_snake_mode(self):
        """重置影子模式游戏状态
        
        初始化玩家蛇、AI1蛇(影子)、AI2蛇(影子)、食物位置和游戏状态变量。
        AI蛇完全模仿玩家的移动和蛇身长度,AI就是影子,AI死亡玩家也会死亡。
        """
        # 计算棋盘中心点
        mid = self.board_size // 2
        
        # 初始化玩家蛇(3节,位于中心)
        self.snake = [(mid + i, mid) for i in range(1, -2, -1)]
        self.snake_set = set(self.snake)
        self.direction = "DOWN"          # 玩家蛇初始方向
        
        # 初始化AI1蛇(3节,位于玩家左侧)
        self.ai1_snake = [(mid + i, mid - 5) for i in range(1, -2, -1)]
        self.ai1_snake_set = set(self.ai1_snake)
        self.ai1_direction = "DOWN"       # AI1蛇初始方向(与玩家相同)
        self.ai1_dead = False
        
        # 初始化AI2蛇(3节,位于玩家右侧)
        self.ai2_snake = [(mid + i, mid + 5) for i in range(1, -2, -1)]
        self.ai2_snake_set = set(self.ai2_snake)
        self.ai2_direction = "DOWN"       # AI2蛇初始方向(与玩家相同)
        self.ai2_dead = False
        
        # 初始化游戏状态
        self.score = 0
        self.ai1_score = 0
        self.ai2_score = 0
        self.death_reason = None
        self.game_start_time = time.time()  # 初始化游戏开始时间
        
        # 更新可用位置集合(排除三条蛇的位置)
        all_snake_positions = set(self.snake + self.ai1_snake + self.ai2_snake)
        self.non_snake = set((r, c) for r in range(self.board_size) for c in range(self.board_size) if (r, c) not in all_snake_positions)
        
        # 生成初始食物
        self.food = self._generate_food()

    # 重置游戏状态(对抗模式)
    def reset_opponent_mode(self):
        """重置游戏状态(对抗模式)
        
        初始化玩家蛇、对抗蛇、食物位置和游戏状态变量。
        """
        # 计算棋盘中心点
        mid = self.board_size // 2
        
        # 初始化玩家蛇(3节,位于中心)
        self.snake = [(mid + i, mid) for i in range(1, -2, -1)]
        self.snake_set = set(self.snake)
        self.direction = "DOWN"          # 玩家蛇初始方向
        
        # 初始化对抗蛇(3节,位于对角位置避免与玩家蛇重叠)
        self.opponent_snake = [(mid - i - 5, mid - 5) for i in range(1, -2, -1)]
        self.opponent_snake_set = set(self.opponent_snake)
        self.opponent_direction = "UP"   # 对抗蛇初始方向(与玩家相反)
        self.opponent_dead = False       # 对抗蛇死亡状态标记
        
        # 初始化游戏状态
        self.score = 0
        self.opponent_score = 0
        self.death_reason = None
        self.game_start_time = time.time()  # 初始化游戏开始时间
        
        # 更新可用位置集合(排除两条蛇的位置)
        self._update_available_positions()
        
        # 生成初始食物
        self.food = self._generate_food()


    # ---------------------------
    # 游戏模式相关设置
    # ---------------------------

    # 执行游戏的一步移动(普通模式)
    def step(self, action):
        """
        执行游戏的一步移动(普通模式)
        
        参数:
            action: -1(不变/无输入),或 0:UP, 1:LEFT, 2:RIGHT, 3:DOWN
            
        返回:
            tuple: (done, info) - done表示游戏是否结束,info包含游戏状态信息
        """
        # 更新方向(如果有新的动作输入)
        if action != -1:
            self._update_direction(action)

        # 计算新的蛇头位置
        row, col = self.snake[0]  # 当前蛇头位置
        if self.direction == "UP":
            row -= 1
        elif self.direction == "DOWN":
            row += 1
        elif self.direction == "LEFT":
            col -= 1
        elif self.direction == "RIGHT":
            col += 1
        
        new_head = (row, col)

        # 初始化状态变量
        done = False
        self.death_reason = None
        food_obtained = False

        # 处理蛇的移动和碰撞检测
        if new_head == self.food:
            # 吃到食物的情况
            food_obtained = True
            self.score += 10
            
            # 播放进食音效(静默失败)
            if self.sound_eat:
                try:
                    self.sound_eat.play()
                except Exception:
                    pass
                    
            # 添加新头部(不删除尾部,蛇长度增加)
            self.snake.insert(0, new_head)
            self.snake_set.add(new_head)
            self.non_snake.discard(new_head)
            
            # 添加吃到食物时的视觉反馈标记
            if not hasattr(self, 'food_effect_timer'):
                self.food_effect_timer = 0
                self.last_food_position = None
            self.last_food_position = new_head  # 记录吃到食物的位置
            self.food_effect_timer = 3  # 持续3帧的视觉效果
        else:
            # 没吃到食物的情况
            # 移除尾格并更新位置集合
            tail = self.snake.pop()
            if tail in self.snake_set:  # 确保tail存在于集合中再移除
                self.snake_set.remove(tail)
            self.non_snake.add(tail)
            
            # 添加新头部
            self.snake.insert(0, new_head)
            self.snake_set.add(new_head)
            self.non_snake.discard(new_head)

        # 检查碰撞条件
        # 1. 撞墙检测
        if row < 0 or row >= self.board_size or col < 0 or col >= self.board_size:
            done = True
            self.death_reason = "撞墙死亡"
        # 2. 撞到自己检测(检查蛇头是否与身体其他部分碰撞)
        elif len(self.snake) > 1 and new_head in self.snake[1:]:
            done = True
            self.death_reason = "撞到自己"

        # 处理游戏结束逻辑
        if done:
            # 播放游戏结束音效(静默失败)
            if self.sound_game_over:
                try:
                    self.sound_game_over.play()
                except Exception:
                    pass
        else:
            # 吃到食物时生成新食物
            if food_obtained:
                self.food = self._generate_food()

        # 构建并返回游戏状态信息
        info = {
            "snake_size": len(self.snake),
            "snake_head_pos": self.snake[0],  # 直接使用元组,避免不必要的转换
            "prev_snake_head_pos": self.snake[1] if len(self.snake) > 1 else self.snake[0],
            "food_pos": self.food,
            "food_obtained": food_obtained,
            "death_reason": self.death_reason
        }

        return done, info

    # 更新可用位置集合,排除两条蛇的位置(对抗模式)
    def _update_available_positions(self):
        """更新所有非蛇体位置的集合
        
        用于路径查找和食物生成时的位置有效性检查。
        """
        # 创建所有可能的位置集合
        all_positions = set((r, c) for r in range(self.board_size) 
                          for c in range(self.board_size))
        
        # 移除玩家蛇占据的位置
        available = all_positions - self.snake_set
        
        # 移除对抗蛇占据的位置(如果存在)
        if hasattr(self, 'opponent_snake_set'):
            available -= self.opponent_snake_set
        
        self.non_snake = available

    # 执行游戏的一步移动(对抗模式)
    def step_opponent_mode(self, action):
        """
        执行游戏的一步移动(对抗模式)
        
        参数:
            action: -1(不变/无输入),或 0:UP, 1:LEFT, 2:RIGHT, 3:DOWN
            
        返回:
            tuple: (done, info) - done表示游戏是否结束,info包含游戏状态信息
        """
        # 更新方向(如果有新的动作输入)
        if action != -1:
            self._update_direction(action)

        # 计算新的蛇头位置
        row, col = self.snake[0]  # 当前蛇头位置
        if self.direction == "UP":
            row -= 1
        elif self.direction == "DOWN":
            row += 1
        elif self.direction == "LEFT":
            col -= 1
        elif self.direction == "RIGHT":
            col += 1
        
        new_head = (row, col)

        # 初始化状态变量
        done = False
        self.death_reason = None
        food_obtained = False

        # 先添加新头部(无论是否吃到食物)
        self.snake.insert(0, new_head)
        self.snake_set.add(new_head)
        self.non_snake.discard(new_head)

        # 检查是否吃到食物
        if new_head == self.food:
            food_obtained = True
            self.score += 10
            
            # 播放进食音效(静默失败)
            if self.sound_eat:
                try:
                    self.sound_eat.play()
                except Exception:
                    pass
                    
            # 添加吃到食物时的视觉反馈标记
            if not hasattr(self, 'food_effect_timer'):
                self.food_effect_timer = 0
                self.last_food_position = None
            self.last_food_position = new_head  # 记录吃到食物的位置
            self.food_effect_timer = 3  # 持续3帧的视觉效果
        else:
            # 没吃到食物时移除尾部(如果蛇长度>1)
            food_obtained = False
            if len(self.snake) > 1:
                tail = self.snake.pop()
                if tail in self.snake_set:  # 确保tail存在于集合中再移除
                    self.snake_set.remove(tail)
                self.non_snake.add(tail)

        # 检查碰撞条件
        # 1. 撞墙检测
        if row < 0 or row >= self.board_size or col < 0 or col >= self.board_size:
            done = True
            self.death_reason = "撞墙死亡"
        # 2. 撞到自己检测(检查蛇头是否与身体其他部分碰撞)
        elif len(self.snake) > 1 and new_head in self.snake[1:]:
            done = True
            self.death_reason = "撞到自己"
        # 3. 撞到对抗蛇检测
        elif new_head in self.opponent_snake_set:
            done = True
            self.death_reason = "撞到对抗蛇"

        # 处理游戏结束逻辑
        if done:
            # 播放游戏结束音效(静默失败)
            if self.sound_game_over:
                try:
                    self.sound_game_over.play()
                except Exception:
                    pass
        else:
            # 吃到食物时生成新食物
            if food_obtained:
                self.food = self._generate_food()

        # 构建并返回游戏状态信息(移除numpy依赖)
        info = {
            "snake_size": len(self.snake),
            "snake_head_pos": self.snake[0],  # 直接使用元组
            "prev_snake_head_pos": self.snake[1] if len(self.snake) > 1 else self.snake[0],
            "food_pos": self.food,
            "food_obtained": food_obtained,
            "death_reason": self.death_reason
        }

        return done, info

    # 执行对抗蛇的一步移动(增强版)
    def opponent_step(self, action):
        """
        处理对抗蛇的移动逻辑(增强版)
        
        参数:
            action: -1(不变/无输入),或 0:UP, 1:LEFT, 2:RIGHT, 3:DOWN
            
        返回:
            tuple: (done, info) - done表示对抗蛇是否死亡,info包含死亡原因
        """
        # 如果对抗蛇已经死亡,则不再移动
        if hasattr(self, 'opponent_dead') and self.opponent_dead:
            return True, {"death_reason": self.death_reason}

        # 更新移动方向(如果有新的动作输入)
        if action != -1:
            self._update_opponent_direction(action)

        # 计算新的对抗蛇头位置
        row, col = self.opponent_snake[0]  # 当前对抗蛇头位置
        if self.opponent_direction == "UP":
            row -= 1
        elif self.opponent_direction == "DOWN":
            row += 1
        elif self.opponent_direction == "LEFT":
            col -= 1
        elif self.opponent_direction == "RIGHT":
            col += 1
        
        new_head = (row, col)

        # 初始化状态变量
        done = False
        death_reason = None

        # 先添加新头部(无论是否吃到食物)
        self.opponent_snake.insert(0, new_head)
        self.opponent_snake_set.add(new_head)

        # 检查碰撞条件
        # 1. 撞墙检测
        if row < 0 or row >= self.board_size or col < 0 or col >= self.board_size:
            done = True
            death_reason = "对抗蛇撞墙死亡"
        # 2. 撞到自己检测(排除刚添加的头部)
        elif new_head in self.opponent_snake_set and new_head != self.opponent_snake[0]:
            done = True
            death_reason = "对抗蛇撞到自己"
        # 3. 撞到玩家蛇检测
        elif new_head in self.snake_set:
            done = True
            death_reason = "对抗蛇撞到玩家蛇"

        # 处理对抗蛇死亡逻辑
        if done:
            self.opponent_dead = True
            self.death_reason = death_reason
            # 为玩家增加额外奖励分数
            self.score += 50  # 击败对抗蛇的奖励
            
            # 播放对抗蛇死亡音效(如果有)
            if hasattr(self, 'sound_crash') and self.sound_crash:
                try:
                    self.sound_crash.play()
                except Exception:
                    pass
            
            return done, {"death_reason": death_reason}

        # 处理移动后的蛇身更新
        if new_head != self.food:
            # 没吃到食物时移除尾部(如果蛇长度>1)
            if len(self.opponent_snake) > 1:
                tail = self.opponent_snake.pop()
                self.opponent_snake_set.remove(tail)
        else:
            # 吃到食物,生成新食物
            self.opponent_score += 10
            
            # 播放对抗蛇进食音效(如果有)
            if hasattr(self, 'sound_eat') and self.sound_eat:
                try:
                    # 调整音量或使用不同音效区分玩家和对抗蛇
                    pygame.mixer.Sound.set_volume(self.sound_eat, 0.5)
                    self.sound_eat.play()
                    pygame.mixer.Sound.set_volume(self.sound_eat, 1.0)  # 恢复原音量
                except Exception:
                    pass
            
            self.food = self._generate_food()
        
        # 更新non_snake集合,确保游戏状态一致性
        self._update_available_positions()

        return done, {"death_reason": death_reason}

    # 重新部署对抗蛇(确保与玩家蛇不重叠)
    def respawn_opponent(self):
        """重新部署对抗蛇"""
        mid = self.board_size // 2
        
        # 尝试最多10次生成有效的对抗蛇位置
        for _ in range(10):
            # 随机选择一个远离玩家的区域
            # 使用边界检查确保位置有效
            opponent_row = random.randint(2, self.board_size - 5)
            opponent_col = random.randint(2, self.board_size - 5)
            
            # 创建对抗蛇(3节)
            new_opponent_snake = [(opponent_row + i, opponent_col) for i in range(1, -2, -1)]
            new_opponent_set = set(new_opponent_snake)
            
            # 检查是否与玩家蛇重叠或越界
            valid_position = True
            for pos in new_opponent_snake:
                r, c = pos
                # 检查是否在棋盘内
                if r < 0 or r >= self.board_size or c < 0 or c >= self.board_size:
                    valid_position = False
                    break
                # 检查是否与玩家蛇重叠
                if pos in self.snake_set:
                    valid_position = False
                    break
            
            if valid_position:
                # 有效位置,更新对抗蛇
                self.opponent_snake = new_opponent_snake
                self.opponent_snake_set = new_opponent_set
                self.opponent_direction = random.choice(["UP", "DOWN", "LEFT", "RIGHT"])
                self.opponent_dead = False
                
                # 重新计算non_snake集合,确保准确性
                self.non_snake = set((r, c) for r in range(self.board_size) for c in range(self.board_size) 
                                  if (r, c) not in self.snake_set and (r, c) not in self.opponent_snake_set and (r, c) != self.food)
                return
        
        # 如果多次尝试都失败,使用安全的默认位置
        self.opponent_snake = [(max(2, mid - 3), max(2, mid - 5)), 
                              (max(2, mid - 4), max(2, mid - 5)), 
                              (max(2, mid - 5), max(2, mid - 5))]
        self.opponent_snake_set = set(self.opponent_snake)
        self.opponent_direction = "UP"
        self.opponent_dead = False
        
        # 重新计算non_snake集合
        self.non_snake = set((r, c) for r in range(self.board_size) for c in range(self.board_size) 
                          if (r, c) not in self.snake_set and (r, c) not in self.opponent_snake_set and (r, c) != self.food)

    # 更新玩家蛇的移动方向(防止180度转向)
    def _update_direction(self, action):
        """
        根据用户操作更新玩家蛇的移动方向
        
        参数:
            action: 0:UP, 1:LEFT, 2:RIGHT, 3:DOWN
        
        说明:
            实现了180度转向限制,防止蛇直接反向移动
        """
        # 使用条件判断直接更新方向,避免不必要的嵌套
        if action == 0 and self.direction != "DOWN":  # 向上且不与当前方向冲突
            self.direction = "UP"
        elif action == 1 and self.direction != "RIGHT":  # 向左且不与当前方向冲突
            self.direction = "LEFT"
        elif action == 2 and self.direction != "LEFT":  # 向右且不与当前方向冲突
            self.direction = "RIGHT"
        elif action == 3 and self.direction != "UP":  # 向下且不与当前方向冲突
            self.direction = "DOWN"

    # 更新对抗蛇的移动方向(防止180度转向)
    def _update_opponent_direction(self, action):
        """
        根据输入更新对抗蛇的移动方向
        
        参数:
            action: 0:UP, 1:LEFT, 2:RIGHT, 3:DOWN
        
        说明:
            实现了180度转向限制,防止对抗蛇直接反向移动
        """
        # 使用条件判断直接更新方向,避免不必要的嵌套
        if action == 0 and self.opponent_direction != "DOWN":  # 向上且不与当前方向冲突
            self.opponent_direction = "UP"
        elif action == 1 and self.opponent_direction != "RIGHT":  # 向左且不与当前方向冲突
            self.opponent_direction = "LEFT"
        elif action == 2 and self.opponent_direction != "LEFT":  # 向右且不与当前方向冲突
            self.opponent_direction = "RIGHT"
        elif action == 3 and self.opponent_direction != "UP":  # 向下且不与当前方向冲突
            self.opponent_direction = "DOWN"

    # 执行游戏的一步移动(影子模式)
    def step_three_snake_mode(self, action):
        """
        影子模式的游戏逻辑步骤
        AI蛇完全模仿玩家的移动和蛇身长度,AI就是影子,AI死亡玩家也死亡
        玩家吃到食物增长蛇身,AI也会增长蛇身
        
        参数:
            action: -1(不变/无输入),或 0:UP, 1:LEFT, 2:RIGHT, 3:DOWN
            
        返回:
            tuple: (done, info) - done表示游戏是否结束,info包含游戏状态信息
        """
        # 确保AI蛇的生命状态属性存在并设置为True
        if not hasattr(self, 'ai1_alive'):
            self.ai1_alive = True
        if not hasattr(self, 'ai2_alive'):
            self.ai2_alive = True
        
        # 初始化状态变量
        done = False
        self.death_reason = None
        food_obtained = False
        
        # 1. 处理玩家蛇的移动 - 传统蛇形移动方式
        if action != -1:
            self._update_direction(action)
        
        # 计算新的蛇头位置
        row, col = self.snake[0]  # 当前蛇头位置
        if self.direction == "UP":
            row -= 1
        elif self.direction == "DOWN":
            row += 1
        elif self.direction == "LEFT":
            col -= 1
        elif self.direction == "RIGHT":
            col += 1
        
        new_head = (row, col)
        
        # 先添加新头部(无论是否吃到食物)
        self.snake.insert(0, new_head)
        if hasattr(self, 'snake_set'):
            self.snake_set.add(new_head)
            self.non_snake.discard(new_head)
        
        # 检查碰撞条件(玩家蛇)
        # 1. 撞墙检测
        if row < 0 or row >= self.board_size or col < 0 or col >= self.board_size:
            done = True
            self.death_reason = "玩家蛇撞墙死亡!"
        # 2. 撞自己检测
        elif new_head in self.snake[1:]:
            done = True
            self.death_reason = "玩家蛇咬到自己!"
        # 3. 撞AI蛇检测
        elif hasattr(self, 'ai1_snake') and new_head in self.ai1_snake:
            done = True
            self.death_reason = "玩家蛇撞到AI1蛇!"
        elif hasattr(self, 'ai2_snake') and new_head in self.ai2_snake:
            done = True
            self.death_reason = "玩家蛇撞到AI2蛇!"
        
        # 2. 处理食物逻辑
        if not done and hasattr(self, 'food') and new_head == self.food:
            food_obtained = True
            self.score += 10
            # 记录最后食物位置用于视觉效果
            if hasattr(self, 'non_snake'):
                # 从可用位置集合中移除旧食物位置
                self.non_snake.discard(self.food)
            # 生成新食物
            self.food = self._generate_food()
        else:
            # 如果没吃到食物,移除尾部(保持蛇长度不变)
            tail = self.snake.pop()
            if hasattr(self, 'snake_set'):
                self.snake_set.discard(tail)
                self.non_snake.add(tail)
        
        # 3. 处理AI蛇的移动 - AI蛇完全模仿玩家移动(作为影子)
        if hasattr(self, 'ai1_snake') and hasattr(self, 'ai2_snake') and not done:
            # 3.1 计算AI1蛇的新位置(位于玩家左侧一定距离)
            shadow_offset1 = -5  # AI1位于玩家左侧5格
            new_ai1_snake = []
            
            for i, (r, c) in enumerate(self.snake):
                # 复制玩家蛇的形状,但水平位置偏移
                new_c = c + shadow_offset1
                # 确保在边界内
                new_c = max(0, min(new_c, self.board_size - 1))
                new_ai1_snake.append((r, new_c))
            
            # 3.2 计算AI2蛇的新位置(位于玩家右侧一定距离)
            shadow_offset2 = 5  # AI2位于玩家右侧5格
            new_ai2_snake = []
            
            for i, (r, c) in enumerate(self.snake):
                # 复制玩家蛇的形状,但水平位置偏移
                new_c = c + shadow_offset2
                # 确保在边界内
                new_c = max(0, min(new_c, self.board_size - 1))
                new_ai2_snake.append((r, new_c))
            
            # 检查AI蛇的碰撞
            # AI1蛇碰撞检测
            ai1_dead = False
            # 检查AI1蛇是否撞墙
            for (r, c) in new_ai1_snake:
                if r < 0 or r >= self.board_size or c < 0 or c >= self.board_size:
                    ai1_dead = True
                    break
            # 检查AI1蛇是否咬自己
            if not ai1_dead and len(set(new_ai1_snake)) != len(new_ai1_snake):
                ai1_dead = True
            # 检查AI1蛇是否撞玩家蛇
            if not ai1_dead and any(pos in self.snake for pos in new_ai1_snake):
                ai1_dead = True
            # 检查AI1蛇是否撞AI2蛇
            if not ai1_dead and any(pos in new_ai2_snake for pos in new_ai1_snake):
                ai1_dead = True
            
            # AI2蛇碰撞检测
            ai2_dead = False
            # 检查AI2蛇是否撞墙
            for (r, c) in new_ai2_snake:
                if r < 0 or r >= self.board_size or c < 0 or c >= self.board_size:
                    ai2_dead = True
                    break
            # 检查AI2蛇是否咬自己
            if not ai2_dead and len(set(new_ai2_snake)) != len(new_ai2_snake):
                ai2_dead = True
            # 检查AI2蛇是否撞玩家蛇
            if not ai2_dead and any(pos in self.snake for pos in new_ai2_snake):
                ai2_dead = True
            # 检查AI2蛇是否撞AI1蛇
            if not ai2_dead and any(pos in new_ai1_snake for pos in new_ai2_snake):
                ai2_dead = True
            
            # 更新AI蛇的生命状态
            self.ai1_alive = not ai1_dead
            self.ai2_alive = not ai2_dead
            
            # 如果任何一条AI蛇死亡,玩家也死亡
            if ai1_dead or ai2_dead:
                done = True
                if ai1_dead and ai2_dead:
                    self.death_reason = "两条影子蛇都死亡了!"
                elif ai1_dead:
                    self.death_reason = "左侧影子蛇死亡了!"
                else:
                    self.death_reason = "右侧影子蛇死亡了!"
            else:
                # 更新AI蛇的位置
                # 先从non_snake中移除旧位置
                if hasattr(self, 'non_snake'):
                    for pos in self.ai1_snake:
                        self.non_snake.add(pos)
                    for pos in self.ai2_snake:
                        self.non_snake.add(pos)
                
                # 更新AI蛇的位置
                self.ai1_snake = new_ai1_snake
                self.ai2_snake = new_ai2_snake
                
                # 从non_snake中添加新位置
                if hasattr(self, 'non_snake'):
                    for pos in self.ai1_snake:
                        self.non_snake.discard(pos)
                    for pos in self.ai2_snake:
                        self.non_snake.discard(pos)
        
        # 返回游戏状态
        info = {
            "death_reason": self.death_reason,
            "score": self.score,
            "food_obtained": food_obtained,
            "ai1_alive": self.ai1_alive,
            "ai2_alive": self.ai2_alive
        }
        
        return done, info

    # 生成食物(确保不在蛇身体或对抗蛇身体上)
    def _generate_food(self):
        """随机在空格里生成食物(若无可用空格则返回 (0,0))"""
        if len(self.non_snake) > 0:
            # 将集合转换为列表后再随机选择
            non_snake_list = list(self.non_snake)
            return non_snake_list[0] if len(non_snake_list) == 1 else random.choice(non_snake_list)
        else:
            return (0, 0)


    # ---------------------------
    # GUI绘制
    # ---------------------------

    # 绘制游戏结束界面
    def draw_game_over_screen(self):
        """绘制游戏结束界面"""
        # 绘制深蓝色渐变背景
        for y in range(self.display_height):
            r = int(0)
            g = int(10)
            b = int(30 - 20 * y / self.display_height)
            pygame.draw.line(self.screen, (r, g, b), (0, y), (self.display_width, y))
            
        margin_top = 60
        spacing = 35
        btn_spacing = 10

        # 标题 - 根据分数显示不同内容和颜色
        if self.score >= 1000:
            title_text = "恭喜胜利!"
            title_color = (255, 255, 100)  # 金黄色标题
            shadow_color = (180, 180, 0)   # 深黄色阴影
        else:
            title_text = "游戏结束"
            title_color = (255, 255, 255)  # 白色标题
            shadow_color = (150, 150, 150) # 灰色阴影
            
        # 标题阴影效果
        title_shadow = self.large_font.render(title_text, True, shadow_color)
        title = self.large_font.render(title_text, True, title_color)
        title_rect = title.get_rect(center=(self.display_width // 2, margin_top))
        
        # 绘制阴影和标题
        shadow_offset = 2
        self.screen.blit(title_shadow, (title_rect.x + shadow_offset, title_rect.y + shadow_offset))
        self.screen.blit(title, title_rect)

        # 分数显示 - 使用更醒目的颜色和更大的字体
        score_text = self.font.render(f"最终分数: {self.score}", True, (255, 255, 150))
        score_rect = score_text.get_rect(center=(self.display_width // 2, title_rect.bottom + spacing))
        self.screen.blit(score_text, score_rect)

        # 蛇身长度
        length = len(self.snake)
        length_text = self.font.render(f"蛇身长度: {length} 格", True, (200, 255, 200))
        length_rect = length_text.get_rect(center=(self.display_width // 2, score_rect.bottom + spacing // 2))
        self.screen.blit(length_text, length_rect)

        # 死亡原因
        reason_rect = None
        if hasattr(self, 'death_reason') and self.death_reason:
            reason_text = self.font.render(f"死亡原因: {self.death_reason}", True, (255, 200, 200))
            reason_rect = reason_text.get_rect(center=(self.display_width // 2, length_rect.bottom + spacing // 2))
            self.screen.blit(reason_text, reason_rect)

        # 绘制按钮
        button_width = 200
        button_height = 60
        button_y = self.display_height // 2
        
        # 重试按钮
        retry_button_rect = pygame.Rect(
            (self.display_width - button_width) // 2,
            button_y,
            button_width,
            button_height
        )
        pygame.draw.rect(self.screen, (0, 150, 0), retry_button_rect, border_radius=10)
        pygame.draw.rect(self.screen, (0, 255, 0), retry_button_rect, 2, border_radius=10)
        retry_text = self.font.render("重试", True, (255, 255, 255))
        retry_text_rect = retry_text.get_rect(center=retry_button_rect.center)
        self.screen.blit(retry_text, retry_text_rect)

        # 菜单按钮
        menu_button_rect = pygame.Rect(
            (self.display_width - button_width) // 2,
            button_y + button_height + btn_spacing,
            button_width,
            button_height
        )
        pygame.draw.rect(self.screen, (100, 100, 150), menu_button_rect, border_radius=10)
        pygame.draw.rect(self.screen, (150, 150, 255), menu_button_rect, 2, border_radius=10)
        menu_text = self.font.render("返回菜单", True, (255, 255, 255))
        menu_text_rect = menu_text.get_rect(center=menu_button_rect.center)
        self.screen.blit(menu_text, menu_text_rect)

        # 退出按钮
        exit_button_rect = pygame.Rect(
            (self.display_width - button_width) // 2,
            button_y + 2 * (button_height + btn_spacing),
            button_width,
            button_height
        )
        pygame.draw.rect(self.screen, (150, 0, 0), exit_button_rect, border_radius=10)
        pygame.draw.rect(self.screen, (255, 0, 0), exit_button_rect, 2, border_radius=10)
        exit_text = self.font.render("退出游戏", True, (255, 255, 255))
        exit_text_rect = exit_text.get_rect(center=exit_button_rect.center)
        self.screen.blit(exit_text, exit_text_rect)
  
    # 绘制游戏界面(包括玩家蛇、对抗蛇和食物)
    def draw_board(self, draw_opponent=False):
        """
        绘制游戏界面,包括棋盘、蛇和食物
        
        参数:
            draw_opponent: 是否绘制对抗蛇
        """
        # 绘制深蓝色渐变背景
        for y in range(self.screen.get_height()):
            # 从深蓝到稍微亮一点的蓝色渐变
            r = max(0, int(10 - 5 * y / self.screen.get_height()))
            g = max(0, int(15 - 8 * y / self.screen.get_height()))
            b = max(20, int(30 + 10 * y / self.screen.get_height()))
            pygame.draw.line(self.screen, (r, g, b), (0, y), (self.screen.get_width(), y))

        # 绘制游戏区域背景
        pygame.draw.rect(self.screen, (10, 15, 30),
                         (self.border_size, self.border_size, self.width, self.height),
                         border_radius=5)
        
        # 绘制棋盘网格线(浅灰色,半透明)和灰色对角线填充
        grid_color = (50, 50, 70, 100)
        # 绘制两条主对角线上的格子填充灰色
        diagonal_color = (40, 40, 60, 150)  # 灰色填充颜色
        for r in range(self.board_size):
            for c in range(self.board_size):
                # 判断是否在主对角线上(左上到右下)或副对角线上(右上到左下)
                if r == c or r + c == self.board_size - 1:
                    # 计算格子的左上角坐标
                    start_x = self.border_size + c * self.cell_size
                    start_y = self.border_size + r * self.cell_size
                    # 填充整个格子为灰色
                    pygame.draw.rect(self.screen, diagonal_color,
                                  (start_x, start_y, self.cell_size, self.cell_size))
        
        # 绘制网格线
        for i in range(1, self.board_size):
            # 垂直线
            x = self.border_size + i * self.cell_size
            pygame.draw.line(self.screen, grid_color, 
                           (x, self.border_size), 
                           (x, self.border_size + self.height),
                           1)
            # 水平线
            y = self.border_size + i * self.cell_size
            pygame.draw.line(self.screen, grid_color, 
                           (self.border_size, y), 
                           (self.border_size + self.width, y),
                           1)

        # 绘制棋盘边框(白色双线,增强视觉效果)
        # 外边框
        pygame.draw.rect(self.screen, (150, 150, 180),
                         (self.border_size - 3, self.border_size - 3, self.width + 6, self.height + 6), 2)
        # 内边框
        pygame.draw.rect(self.screen, (200, 200, 255),
                         (self.border_size - 1, self.border_size - 1, self.width + 2, self.height + 2), 1)

        # 绘制玩家蛇
        self.draw_snake()
        
        # 绘制对抗蛇(仅在对抗模式且对抗蛇未死亡时)
        opponent_alive = hasattr(self, 'opponent_snake') and (
            not hasattr(self, 'opponent_dead') or not self.opponent_dead
        )
        if draw_opponent and opponent_alive:
            self.draw_opponent_snake()
        
        # 绘制AI1蛇(影子模式)
        ai1_alive = hasattr(self, 'ai1_snake') and (not hasattr(self, 'ai1_dead') or not self.ai1_dead)
        if ai1_alive:
            self.draw_ai_3snake('ai1')
        
        # 绘制AI2蛇(影子模式)
        ai2_alive = hasattr(self, 'ai2_snake') and (not hasattr(self, 'ai2_dead') or not self.ai2_dead)
        if ai2_alive:
            self.draw_ai_3snake('ai2')

        # 绘制食物 - 使用更吸引人的样式,带有立体感和脉动效果
        if len(self.snake) < self.grid_size:
            r, c = self.food
            food_x = c * self.cell_size + self.border_size
            food_y = r * self.cell_size + self.border_size
            
            # 添加脉动动画效果
            if not hasattr(self, 'food_pulse_timer'):
                self.food_pulse_timer = 0
            self.food_pulse_timer = (self.food_pulse_timer + 1) % 60
            pulse_factor = 1.0 + 0.1 * abs(30 - self.food_pulse_timer) / 30
            
            # 计算食物大小
            base_size = self.cell_size * 0.8
            current_size = base_size * pulse_factor
            offset = (self.cell_size - current_size) // 2
            
            # 食物阴影(增加立体感)
            shadow_offset = 2
            pygame.draw.circle(self.screen, (150, 10, 10),
                              (food_x + self.cell_size // 2 + shadow_offset, 
                               food_y + self.cell_size // 2 + shadow_offset),
                              current_size // 2)
            
            # 食物主体(渐变色圆形)
            # 创建径向渐变效果的surface
            food_surf = pygame.Surface((self.cell_size, self.cell_size), pygame.SRCALPHA)
            center = (self.cell_size // 2, self.cell_size // 2)
            radius = int(current_size // 2)
            
            # 从中心到边缘的径向渐变
            for i in range(radius, 0, -1):
                intensity = 255 - (radius - i) * 255 // radius
                color = (255, intensity // 5, intensity // 5)
                pygame.draw.circle(food_surf, color, center, i)
            
            # 将渐变效果绘制到屏幕
            self.screen.blit(food_surf, (food_x, food_y))
            
            # 食物高光(增加光泽感)
            highlight_size = max(1, current_size // 4)
            pygame.draw.circle(self.screen, (255, 255, 255),
                              (food_x + self.cell_size // 2 - offset, 
                               food_y + self.cell_size // 2 - offset),
                              highlight_size)
            
            # 食物细节点缀(装饰效果)
            decor_size = max(1, current_size // 8)
            decor_positions = [
                (food_x + self.cell_size // 4, food_y + self.cell_size // 4),
                (food_x + self.cell_size * 3 // 4, food_y + self.cell_size // 4),
                (food_x + self.cell_size // 4, food_y + self.cell_size * 3 // 4),
                (food_x + self.cell_size * 3 // 4, food_y + self.cell_size * 3 // 4)
            ]
            
            for pos in decor_positions:
                pygame.draw.circle(self.screen, (255, 255, 255, 180), pos, decor_size)
        
        # 绘制吃到食物时的视觉反馈效果
        if hasattr(self, 'food_effect_timer') and self.food_effect_timer > 0 and hasattr(self, 'last_food_position') and self.last_food_position:
            # 计算效果的屏幕坐标
            r, c = self.last_food_position
            effect_x = c * self.cell_size + self.border_size
            effect_y = r * self.cell_size + self.border_size
            
            # 根据计时器计算效果大小和透明度
            size_factor = 1.0 + (3 - self.food_effect_timer) * 0.3
            opacity = 255 - (3 - self.food_effect_timer) * 85
            
            # 创建一个临时的surface用于绘制带透明度的效果
            effect_surf = pygame.Surface((self.cell_size * 2, self.cell_size * 2), pygame.SRCALPHA)
            
            # 绘制食物效果的外环(带有渐变效果)
            for i in range(5):
                current_size = int(self.cell_size * size_factor * (1 - i * 0.15))
                current_opacity = int(opacity * (1 - i * 0.2))
                pygame.draw.circle(
                    effect_surf,
                    (255, 255, 50, current_opacity),  # 黄色带透明度
                    (self.cell_size, self.cell_size),
                    current_size // 2
                )
            
            # 将效果绘制到屏幕上
            self.screen.blit(effect_surf, (effect_x - self.cell_size // 2, effect_y - self.cell_size // 2))
            
            # 减少计时器
            self.food_effect_timer -= 1

    # 绘制对抗蛇(包括头部和眼睛)
    def draw_opponent_snake(self):
        """绘制对抗蛇(包括头部和眼睛)"""
        head_r, head_c = self.opponent_snake[0]
        head_x = head_c * self.cell_size + self.border_size
        head_y = head_r * self.cell_size + self.border_size

        # 绘制蛇头(深红色调,更有质感)
        snake_head_color = (180, 0, 0)  # 更深的红色
        pygame.draw.polygon(self.screen, snake_head_color, [
            (head_x + self.cell_size // 2, head_y),
            (head_x + self.cell_size, head_y + self.cell_size // 2),
            (head_x + self.cell_size // 2, head_y + self.cell_size),
            (head_x, head_y + self.cell_size // 2)
        ])
        
        # 添加头部光泽效果
        highlight_color = (220, 80, 80)
        highlight_points = [
            (head_x + self.cell_size // 2, head_y + self.cell_size // 5),
            (head_x + self.cell_size * 0.8, head_y + self.cell_size // 2),
            (head_x + self.cell_size // 2, head_y + self.cell_size * 0.4),
            (head_x + self.cell_size * 0.2, head_y + self.cell_size // 2)
        ]
        pygame.draw.polygon(self.screen, highlight_color, highlight_points)

        # 眼睛 - 根据当前方向调整眼睛位置,增强视觉反馈
        eye_size = max(2, self.cell_size // 12)  # 根据单元格大小动态调整
        eye_offset = self.cell_size // 4
        
        # 根据移动方向调整眼睛位置,让蛇看起来朝移动方向看
        if self.opponent_direction == "UP":
            eye1_pos = (head_x + eye_offset, head_y + eye_offset)
            eye2_pos = (head_x + self.cell_size - eye_offset, head_y + eye_offset)
        elif self.opponent_direction == "DOWN":
            eye1_pos = (head_x + eye_offset, head_y + self.cell_size - eye_offset)
            eye2_pos = (head_x + self.cell_size - eye_offset, head_y + self.cell_size - eye_offset)
        elif self.opponent_direction == "LEFT":
            eye1_pos = (head_x + eye_offset, head_y + eye_offset)
            eye2_pos = (head_x + eye_offset, head_y + self.cell_size - eye_offset)
        else:  # RIGHT
            eye1_pos = (head_x + self.cell_size - eye_offset, head_y + eye_offset)
            eye2_pos = (head_x + self.cell_size - eye_offset, head_y + self.cell_size - eye_offset)
        
        # 绘制眼睛和瞳孔
        pygame.draw.circle(self.screen, (255, 255, 255), eye1_pos, eye_size)
        pygame.draw.circle(self.screen, (255, 255, 255), eye2_pos, eye_size)
        pygame.draw.circle(self.screen, (0, 0, 0), eye1_pos, eye_size // 2)
        pygame.draw.circle(self.screen, (0, 0, 0), eye2_pos, eye_size // 2)
        
        # 绘制身体部分
        for i, (r, c) in enumerate(self.opponent_snake[1:]):
            body_x = c * self.cell_size + self.border_size
            body_y = r * self.cell_size + self.border_size
            # 使用稍微浅一点的红色表示身体
            body_color = (200, 50, 50)
            pygame.draw.rect(self.screen, body_color, (body_x, body_y, self.cell_size, self.cell_size), border_radius=5)

    # 绘制AI蛇(影子模式)
    def draw_ai_3snake(self, ai_type):
        """
        绘制AI蛇(影子模式)
        
        参数:
            ai_type: 'ai1' 或 'ai2'
        """
        # 根据AI类型选择蛇的属性
        if ai_type == 'ai1':
            snake = self.ai1_snake
            direction = self.ai1_direction
            # AI1蛇使用蓝色
            head_color = (0, 150, 255)
            body_color = (0, 100, 255)
        else:  # ai2
            snake = self.ai2_snake
            direction = self.ai2_direction
            # AI2蛇使用紫色
            head_color = (150, 0, 255)
            body_color = (100, 0, 255)
        
        # 绘制蛇身
        for i, (r, c) in enumerate(snake):
            x = c * self.cell_size + self.border_size
            y = r * self.cell_size + self.border_size
            
            # 蛇头特殊绘制
            if i == 0:
                # 绘制蛇头(多边形)
                pygame.draw.polygon(self.screen, head_color, [
                    (x + self.cell_size // 2, y),
                    (x + self.cell_size, y + self.cell_size // 2),
                    (x + self.cell_size // 2, y + self.cell_size),
                    (x, y + self.cell_size // 2)
                ])
                
                # 添加头部光泽效果
                highlight_color = (min(head_color[0] + 40, 255), min(head_color[1] + 40, 255), min(head_color[2] + 40, 255))
                highlight_points = [
                    (x + self.cell_size // 2, y + self.cell_size // 5),
                    (x + self.cell_size * 0.8, y + self.cell_size // 2),
                    (x + self.cell_size // 2, y + self.cell_size * 0.4),
                    (x + self.cell_size * 0.2, y + self.cell_size // 2)
                ]
                pygame.draw.polygon(self.screen, highlight_color, highlight_points)
                
                # 绘制眼睛(根据移动方向调整位置)
                eye_size = max(2, self.cell_size // 12)
                eye_offset = self.cell_size // 4
                
                if direction == "UP":
                    eye1_pos = (x + eye_offset, y + eye_offset)
                    eye2_pos = (x + self.cell_size - eye_offset, y + eye_offset)
                elif direction == "DOWN":
                    eye1_pos = (x + eye_offset, y + self.cell_size - eye_offset)
                    eye2_pos = (x + self.cell_size - eye_offset, y + self.cell_size - eye_offset)
                elif direction == "LEFT":
                    eye1_pos = (x + eye_offset, y + eye_offset)
                    eye2_pos = (x + eye_offset, y + self.cell_size - eye_offset)
                else:  # RIGHT
                    eye1_pos = (x + self.cell_size - eye_offset, y + eye_offset)
                    eye2_pos = (x + self.cell_size - eye_offset, y + self.cell_size - eye_offset)
                
                # 绘制眼睛和瞳孔
                pygame.draw.circle(self.screen, (255, 255, 255), eye1_pos, eye_size)
                pygame.draw.circle(self.screen, (255, 255, 255), eye2_pos, eye_size)
                pygame.draw.circle(self.screen, (0, 0, 0), eye1_pos, eye_size // 2)
                pygame.draw.circle(self.screen, (0, 0, 0), eye2_pos, eye_size // 2)
            else:
                # 绘制蛇身
                pygame.draw.rect(self.screen, body_color, (x, y, self.cell_size, self.cell_size), border_radius=5)
        
        # 绘制蛇身体(渐变效果)
        snake_to_draw = self.ai1_snake if ai_type == 'ai1' else self.ai2_snake
        for i, (r, c) in enumerate(snake_to_draw[1:]):
            segment_x = c * self.cell_size + self.border_size
            segment_y = r * self.cell_size + self.border_size
            
            # 根据位置计算渐变色(立方函数,更自然的过渡)
            total_segments = len(snake_to_draw) - 1
            if total_segments > 0:
                progress = 1 - (i / total_segments)
                # 使用立方函数让颜色变化更自然
                progress_cubed = progress ** 3
                
                # 蓝色/紫色渐变:从头部附近的亮色到尾部的暗色
                if ai_type == 'ai1':
                    # 蓝色渐变
                    blue_intensity = int(150 + 105 * progress_cubed)
                    red_green = int(50 + 50 * progress_cubed)
                else:
                    # 紫色渐变
                    red_intensity = int(100 + 100 * progress_cubed)
                    blue_intensity = int(100 + 100 * progress_cubed)
                    green_intensity = int(20 + 30 * progress_cubed)
                
                # 添加一点随机性使身体更有趣
                random_offset = random.randint(-5, 5)
                if ai_type == 'ai1':
                    # 蓝色渐变颜色
                    segment_color = (max(30, min(200, red_green + random_offset)), 
                                    max(0, min(50, red_green + random_offset)), 
                                    max(0, min(255, blue_intensity + random_offset)))
                else:
                    # 紫色渐变颜色
                    segment_color = (max(30, min(200, red_intensity + random_offset)), 
                                    max(0, min(50, green_intensity + random_offset)), 
                                    max(0, min(200, blue_intensity + random_offset)))
                
                # 绘制带圆角的矩形身体
                rect = pygame.Rect(segment_x + 2, segment_y + 2, 
                                  self.cell_size - 4, self.cell_size - 4)
                pygame.draw.rect(self.screen, segment_color, rect, border_radius=5)
                
                # 添加高光效果
                highlight_rect = pygame.Rect(segment_x + 3, segment_y + 3, 
                                          self.cell_size - 8, self.cell_size // 3)
                highlight_color = (min(255, segment_color[0] + 40), 
                                  min(255, segment_color[1] + 40), 
                                  min(255, segment_color[2] + 40))
                pygame.draw.rect(self.screen, highlight_color, highlight_rect, border_radius=2)
            
            # 尾部尖端处理
            if i == total_segments - 1 and total_segments > 1:
                prev_r, prev_c = snake_to_draw[-2]
                # 确定尾部方向
                if prev_r < r:  # 尾部向下
                    pygame.draw.polygon(self.screen, segment_color, [
                        (segment_x + self.cell_size // 2, segment_y),
                        (segment_x, segment_y + self.cell_size),
                        (segment_x + self.cell_size, segment_y + self.cell_size)
                    ])
                elif prev_r > r:  # 尾部向上
                    pygame.draw.polygon(self.screen, segment_color, [
                        (segment_x + self.cell_size // 2, segment_y + self.cell_size),
                        (segment_x, segment_y),
                        (segment_x + self.cell_size, segment_y)
                    ])
                elif prev_c < c:  # 尾部向右
                    pygame.draw.polygon(self.screen, segment_color, [
                        (segment_x, segment_y + self.cell_size // 2),
                        (segment_x + self.cell_size, segment_y),
                        (segment_x + self.cell_size, segment_y + self.cell_size)
                    ])
                else:  # 尾部向左
                    pygame.draw.polygon(self.screen, segment_color, [
                        (segment_x + self.cell_size, segment_y + self.cell_size // 2),
                        (segment_x, segment_y),
                        (segment_x, segment_y + self.cell_size)
                    ])
            # 删除错误的眼睛绘制代码

        # 绘制身体 - 使用渐变效果,与玩家蛇风格一致
        # 这部分代码已经在上面实现,此处为重复代码,需要删除
            
            # 删除重复代码

    # 绘制玩家蛇(头、眼、身体渐变)
    def draw_snake(self):
        """绘制蛇(头、眼、身体渐变)"""
        # 头坐标换算为像素
        head_r, head_c = self.snake[0]
        head_x = head_c * self.cell_size + self.border_size
        head_y = head_r * self.cell_size + self.border_size

        # 头(蓝色多边形)- 使用更深的蓝色,添加光泽效果
        head_color = (80, 120, 255)
        pygame.draw.polygon(self.screen, head_color, [
            (head_x + self.cell_size // 2, head_y),
            (head_x + self.cell_size, head_y + self.cell_size // 2),
            (head_x + self.cell_size // 2, head_y + self.cell_size),
            (head_x, head_y + self.cell_size // 2)
        ])
        
        # 添加蛇头光泽效果
        gloss_points = [
            (head_x + self.cell_size // 3, head_y + self.cell_size // 4),
            (head_x + self.cell_size // 2, head_y + self.cell_size // 3),
            (head_x + 2 * self.cell_size // 3, head_y + self.cell_size // 4),
            (head_x + self.cell_size // 2, head_y + self.cell_size // 2)
        ]
        pygame.draw.polygon(self.screen, (150, 180, 255), gloss_points)

        # 眼睛 - 根据当前方向调整眼睛位置,增强视觉反馈
        eye_size = max(3, self.cell_size // 6)
        pupil_size = max(1, eye_size // 2)
        eye_offset = self.cell_size // 4
        
        # 根据移动方向调整眼睛位置,让蛇看起来朝移动方向看
        if self.direction == "UP":
            eye_y_offset = -eye_offset
            eye_x_offset1 = -eye_offset
            eye_x_offset2 = eye_offset
        elif self.direction == "DOWN":
            eye_y_offset = eye_offset
            eye_x_offset1 = -eye_offset
            eye_x_offset2 = eye_offset
        elif self.direction == "LEFT":
            eye_x_offset1 = -eye_offset
            eye_x_offset2 = -eye_offset
            eye_y_offset1 = -eye_offset
            eye_y_offset2 = eye_offset
        else:  # RIGHT
            eye_x_offset1 = eye_offset
            eye_x_offset2 = eye_offset
            eye_y_offset1 = -eye_offset
            eye_y_offset2 = eye_offset
        
        # 绘制眼睛
        if self.direction in ["LEFT", "RIGHT"]:
            # 左眼
            pygame.draw.circle(self.screen, (255, 255, 255), 
                              (head_x + self.cell_size // 2 + eye_x_offset1, 
                               head_y + self.cell_size // 2 + eye_y_offset1), 
                              eye_size)
            # 左眼瞳孔
            pygame.draw.circle(self.screen, (0, 0, 0), 
                              (head_x + self.cell_size // 2 + eye_x_offset1 + 
                               (eye_x_offset1 // abs(eye_x_offset1) if eye_x_offset1 != 0 else 0) * 2, 
                               head_y + self.cell_size // 2 + eye_y_offset1), 
                              pupil_size)
            # 右眼
            pygame.draw.circle(self.screen, (255, 255, 255), 
                              (head_x + self.cell_size // 2 + eye_x_offset2, 
                               head_y + self.cell_size // 2 + eye_y_offset2), 
                              eye_size)
            # 右眼瞳孔
            pygame.draw.circle(self.screen, (0, 0, 0), 
                              (head_x + self.cell_size // 2 + eye_x_offset2 + 
                               (eye_x_offset2 // abs(eye_x_offset2) if eye_x_offset2 != 0 else 0) * 2, 
                               head_y + self.cell_size // 2 + eye_y_offset2), 
                              pupil_size)
        else:  # UP, DOWN
            # 左眼
            pygame.draw.circle(self.screen, (255, 255, 255), 
                              (head_x + self.cell_size // 2 + eye_x_offset1, 
                               head_y + self.cell_size // 2 + eye_y_offset), 
                              eye_size)
            # 左眼瞳孔
            pygame.draw.circle(self.screen, (0, 0, 0), 
                              (head_x + self.cell_size // 2 + eye_x_offset1, 
                               head_y + self.cell_size // 2 + eye_y_offset + 
                               (eye_y_offset // abs(eye_y_offset) if eye_y_offset != 0 else 0) * 2), 
                              pupil_size)
            # 右眼
            pygame.draw.circle(self.screen, (255, 255, 255), 
                              (head_x + self.cell_size // 2 + eye_x_offset2, 
                               head_y + self.cell_size // 2 + eye_y_offset), 
                              eye_size)
            # 右眼瞳孔
            pygame.draw.circle(self.screen, (0, 0, 0), 
                              (head_x + self.cell_size // 2 + eye_x_offset2, 
                               head_y + self.cell_size // 2 + eye_y_offset + 
                               (eye_y_offset // abs(eye_y_offset) if eye_y_offset != 0 else 0) * 2), 
                              pupil_size)

        # 身体渐变(增强视觉效果)
        body_length = len(self.snake) - 1
        for i, (r, c) in enumerate(self.snake[1:]):
            body_x = c * self.cell_size + self.border_size
            body_y = r * self.cell_size + self.border_size
            
            # 计算渐变颜色 - 更平滑的渐变效果
            progress = i / max(body_length, 1)
            # 使用立方函数使渐变更自然
            green_intensity = int(255 - (155 * progress * progress * progress))
            
            # 根据不同部分使用微妙的颜色变化
            if i == 0:  # 靠近头部的第一节
                color = (50, green_intensity, 50)
            else:
                # 身体部分使用稍微不同的绿色色调
                green_variation = random.randint(-15, 15)  # 添加一点随机性
                color = (0, max(50, min(255, green_intensity + green_variation)), 0)
            
            # 绘制身体段,使用更大的圆角
            pygame.draw.rect(self.screen, color, 
                           (body_x, body_y, self.cell_size, self.cell_size), 
                           border_radius=max(4, self.cell_size // 3))
            
            # 添加身体高光效果
            highlight_rect = pygame.Rect(
                body_x + self.cell_size // 4,
                body_y + self.cell_size // 4,
                self.cell_size // 2,
                self.cell_size // 4
            )
            highlight_color = tuple(min(255, c + 30) for c in color)
            pygame.draw.rect(self.screen, highlight_color, highlight_rect, border_radius=2)
            
            # 尾部特殊处理
            if i == body_length - 1:
                # 尾部尖端效果
                tail_center_x = body_x + self.cell_size // 2
                tail_center_y = body_y + self.cell_size // 2
                # 确定尾部方向
                if i > 0:
                    prev_r, prev_c = self.snake[-2]
                    if prev_r < r:  # 尾部向下
                        pygame.draw.polygon(self.screen, color, [
                            (tail_center_x - self.cell_size // 3, tail_center_y - self.cell_size // 4),
                            (tail_center_x + self.cell_size // 3, tail_center_y - self.cell_size // 4),
                            (tail_center_x, tail_center_y + self.cell_size // 2)
                        ])
                    elif prev_r > r:  # 尾部向上
                        pygame.draw.polygon(self.screen, color, [
                            (tail_center_x - self.cell_size // 3, tail_center_y + self.cell_size // 4),
                            (tail_center_x + self.cell_size // 3, tail_center_y + self.cell_size // 4),
                            (tail_center_x, tail_center_y - self.cell_size // 2)
                        ])
                    elif prev_c < c:  # 尾部向右
                        pygame.draw.polygon(self.screen, color, [
                            (tail_center_x - self.cell_size // 4, tail_center_y - self.cell_size // 3),
                            (tail_center_x - self.cell_size // 4, tail_center_y + self.cell_size // 3),
                            (tail_center_x + self.cell_size // 2, tail_center_y)
                        ])
                    elif prev_c > c:  # 尾部向左
                        pygame.draw.polygon(self.screen, color, [
                            (tail_center_x + self.cell_size // 4, tail_center_y - self.cell_size // 3),
                            (tail_center_x + self.cell_size // 4, tail_center_y + self.cell_size // 3),
                            (tail_center_x - self.cell_size // 2, tail_center_y)
                        ])

    # 绘制右侧控制面板(玩家蛇信息、对抗蛇信息、AI连接按钮)
    def draw_side_panel(self, ai_connected, show_ai=True):
        """
        在右侧绘制控制面板:
        - 分数、长度
        - 对抗模式下显示对抗蛇信息
        - AI 连接按钮和状态
        """
        panel_x = self.width + self.border_size + 20
        panel_y = self.border_size
        panel_width = 200

        # 绘制面板背景(半透明,增强视觉层次感)
        panel_bg_rect = pygame.Rect(panel_x - 10, panel_y, panel_width, 400)
        pygame.draw.rect(self.screen, (30, 30, 30, 180), panel_bg_rect, border_radius=10)
        pygame.draw.rect(self.screen, (80, 80, 80), panel_bg_rect, border_radius=10, width=1)

        # 标题
        title_surf = self.large_font.render("控制面板", True, (220, 220, 220))
        self.screen.blit(title_surf, (panel_x, panel_y))

        panel_y += 60

        # 玩家蛇信息
        score_surf = self.font.render(f"玩家分数: {self.score}", True, (255, 255, 255))
        self.screen.blit(score_surf, (panel_x, panel_y))
        panel_y += 25
        size_surf = self.font.render(f"蛇长: {len(self.snake)}", True, (255, 255, 255))
        self.screen.blit(size_surf, (panel_x, panel_y))
        panel_y += 25
        
        # 显示当前等级/速度信息
        speed_level = max(1, int(self.speed / 5))
        speed_surf = self.font.render(f"速度等级: {speed_level}", True, (200, 200, 255))
        self.screen.blit(speed_surf, (panel_x, panel_y))
        panel_y += 35

        # 对抗模式信息(如果存在对抗蛇)
        if hasattr(self, 'opponent_snake'):
            # 显示对抗蛇分数和状态
            opponent_status = "存活" if (not hasattr(self, 'opponent_dead') or not self.opponent_dead) else "已死亡"
            opponent_status_color = (255, 100, 100) if opponent_status == "已死亡" else (200, 200, 200)
            
            opponent_title_surf = self.font.render("对抗蛇信息:", True, (220, 100, 100))
            self.screen.blit(opponent_title_surf, (panel_x, panel_y))
            panel_y += 25
            
            # 对抗蛇分数
            opponent_score = getattr(self, 'opponent_score', 0)
            opponent_score_surf = self.font.render(f"分数: {opponent_score}", True, (255, 255, 255))
            self.screen.blit(opponent_score_surf, (panel_x + 10, panel_y))
            panel_y += 25
            
            # 对抗蛇状态
            opponent_status_surf = self.font.render(f"状态: {opponent_status}", True, opponent_status_color)
            self.screen.blit(opponent_status_surf, (panel_x + 10, panel_y))
            panel_y += 35

        # 只在普通模式下显示AI相关内容
        if show_ai:
            # AI 状态显示
            status_text = "已连接" if ai_connected else "已断开"
            status_color = (100, 255, 100) if ai_connected else (255, 100, 100)
            status_surf = self.font.render(f"AI 状态: {status_text}", True, status_color)
            self.screen.blit(status_surf, (panel_x, panel_y))
            panel_y += 40

            # 绘制按钮(Connect/Disconnect)- 改进视觉效果
            self.ai_button_rect = pygame.Rect(panel_x, panel_y, 160, 36)
            mouse_pos = pygame.mouse.get_pos()
            hovering = self.ai_button_rect.collidepoint(mouse_pos)
            
            # 按钮背景和边框效果
            bg_color = (100, 180, 255) if ai_connected else (100, 255, 150)
            hover_color = (150, 210, 255) if ai_connected else (150, 255, 200)
            border_color = (200, 200, 200)
            
            button_color = hover_color if hovering else bg_color
            pygame.draw.rect(self.screen, button_color, self.ai_button_rect, border_radius=8)
            pygame.draw.rect(self.screen, border_color, self.ai_button_rect, border_radius=8, width=2)
            
            # 按钮文字
            btn_text = "断开 AI" if ai_connected else "接通 AI"
            btn_surf = self.font.render(btn_text, True, (20, 20, 20))
            btn_rect = btn_surf.get_rect(center=self.ai_button_rect.center)
            self.screen.blit(btn_surf, btn_rect)

    # 绘制游戏界面(棋盘 + 右侧面板)
    def render(self, ai_connected=False, draw_opponent=False, show_ai=True):
        """综合绘制函数:棋盘 + 右侧面板"""
        self.draw_board(draw_opponent)
        self.draw_side_panel(ai_connected, show_ai)
        pygame.display.flip()

    # 判断鼠标是否在矩形区域内
    def is_mouse_on_rect(self, rect):
        """判断鼠标是否在给定 rect 上(rect 为 pygame.Rect)"""
        return rect.collidepoint(pygame.mouse.get_pos())


# ---------------------------
# AI 行为接口
# ---------------------------
def get_ai_action(game, is_opponent=False):
    """
    智能AI策略:支持控制对抗蛇
    优化版本:集成A*搜索、智能空间评估、循环检测和长期生存策略
    对抗模式增强:添加攻击玩家、包围、食物竞争和防御策略
    is_opponent: True=控制红色对抗蛇,False=控制绿色玩家蛇
    """
    # 根据控制对象选择蛇的信息
    if is_opponent:
        snake = game.opponent_snake
        direction = game.opponent_direction
        # 使用现有的opponent_snake_set提高性能
        if hasattr(game, 'opponent_snake_set'):
            body = game.opponent_snake_set
        else:
            body = set(snake)
        # 获取对抗蛇特定的信息
        if hasattr(game, 'opponent_score'):
            score = game.opponent_score
        else:
            score = len(snake) - 3  # 默认初始长度为3
        
        # 获取玩家蛇信息(对抗模式特有)
        if hasattr(game, 'snake'):
            player_snake = game.snake
            player_head = player_snake[0] if player_snake else None
            player_body = set(player_snake) if player_snake else set()
        else:
            player_snake = []
            player_head = None
            player_body = set()
    else:
        snake = game.snake
        direction = game.direction
        # 使用现有的snake_set提高性能
        if hasattr(game, 'snake_set'):
            body = game.snake_set
        else:
            body = set(snake)
        score = game.score
        
        # 非对抗模式时初始化玩家相关变量
        player_snake = []
        player_head = None
        player_body = set()
    


    head = snake[0]
    food = game.food
    board = game.board_size
    snake_length = len(snake)
    
    # 计算游戏进度百分比
    board_area = board * board
    game_progress = snake_length / board_area

    # 方向映射
    dirs = {
        0: (-1, 0),  # 上
        1: (0, -1),  # 左
        2: (0, 1),   # 右
        3: (1, 0)    # 下
    }

    # 方向名称映射
    dir_names = {
        0: "UP",
        1: "LEFT",
        2: "RIGHT",
        3: "DOWN"
    }

    opposite = {"UP": 3, "DOWN": 0, "LEFT": 2, "RIGHT": 1}
    opposite_dir = opposite.get(direction, -1)  # 使用对应蛇的当前方向

    # 检查位置是否有效
    def is_valid(pos):
        r, c = pos
        return 0 <= r < board and 0 <= c < board and (r, c) not in body
    
    # 曼哈顿距离计算
    def manhattan_dist(pos1, pos2):
        return abs(pos1[0] - pos2[0]) + abs(pos1[1] - pos2[1])
    
    # 欧几里得距离计算
    def euclidean_dist(pos1, pos2):
        return ((pos1[0] - pos2[0]) ** 2 + (pos1[1] - pos2[1]) ** 2) ** 0.5
    
    # ----------------------------------------------------------------------
    # � A*搜索算法:更智能的路径规划
    # ----------------------------------------------------------------------
    def a_star_path(start, goal):
        """优化版A*搜索算法:限制搜索范围,使用更高效的数据结构,支持障碍物检测"""
        # 快速检查目标是否已被占据
        if goal in body:
            return None, float('inf')
            
        # 如果起点就是终点
        if start == goal:
            return [], 0
        
        # 优化:限制搜索深度,避免在复杂情况下无限搜索
        max_search_steps = min(board * board // 2, 1000)
        search_steps = 0
        
        # 开放列表和关闭列表 - 使用集合加速检查
        open_set = []
        open_positions = set()  # 额外集合用于快速检查
        heapq.heappush(open_set, (0, start))
        open_positions.add(start)
        
        came_from = {}
        g_score = {start: 0}  # 从起点到当前点的实际代价
        f_score = {start: manhattan_dist(start, goal)}  # 使用优化的距离函数
        
        # 优化:预计算方向列表
        dir_list = list(dirs.items())
        
        while open_set and search_steps < max_search_steps:
            search_steps += 1
            _, current = heapq.heappop(open_set)
            open_positions.remove(current)
            
            if current == goal:
                # 重建路径
                path = []
                while current in came_from:
                    prev_pos, dir_taken = came_from[current]
                    path.append(dir_taken)
                    current = prev_pos
                path.reverse()
                return path, g_score[goal]
            
            # 优化:游戏后期减少搜索分支
            dirs_to_check = dir_list
            if game_progress > 0.6:
                # 只检查较少的方向,优先选择朝向食物的方向
                hx, hy = current
                fx, fy = goal
                preferred_dirs = []
                if hx > fx: preferred_dirs.append((0, (-1, 0)))
                if hx < fx: preferred_dirs.append((3, (1, 0)))
                if hy > fy: preferred_dirs.append((1, (0, -1)))
                if hy < fy: preferred_dirs.append((2, (0, 1)))
                
                # 最多检查3个方向
                dirs_to_check = preferred_dirs[:3] if preferred_dirs else dir_list[:3]
            
            for d, (dr, dc) in dirs_to_check:
                r, c = current
                neighbor = (r + dr, c + dc)
                
                if 0 <= neighbor[0] < board and 0 <= neighbor[1] < board and neighbor not in body:
                    tentative_g_score = g_score[current] + 1
                    
                    # 优化:动态启发式因子,基于游戏进度
                    heuristic_factor = 1.0 - min(0.5, game_progress * 0.5)
                    
                    if neighbor not in g_score or tentative_g_score < g_score[neighbor]:
                        came_from[neighbor] = (current, d)
                        g_score[neighbor] = tentative_g_score
                        f_score[neighbor] = tentative_g_score + heuristic_factor * manhattan_dist(neighbor, goal)
                        
                        # 优化:使用集合快速检查
                        if neighbor not in open_positions:
                            heapq.heappush(open_set, (f_score[neighbor], neighbor))
                            open_positions.add(neighbor)
        
        return None, float('inf')
    
    # ----------------------------------------------------------------------
    # 🏃 智能空间评估:考虑蛇身体增长后的安全空间
    # ----------------------------------------------------------------------
    def advanced_flood_fill(start):
        """
        优化版洪水填充算法,评估移动方向的安全性,支持障碍物检测
        增加:搜索深度限制、提前剪枝、更高效的评分计算
        """
        # 快速检查起点是否有效
        if start in body or not (0 <= start[0] < board and 0 <= start[1] < board):
            return 1  # 返回最小值
            
        q = deque([start])
        seen = {start}
        
        # 记录每个位置到起点的距离
        distance_map = {start: 0}
        
        # 优化:限制搜索深度,避免在大棋盘上过度计算
        max_search_nodes = min(board * board // 2, 500)
        nodes_count = 0
        
        # 优化:预计算方向列表
        dir_values = list(dirs.values())
        
        # 计算空间的连通性指标
        while q and nodes_count < max_search_nodes:
            nodes_count += 1
            r, c = q.popleft()
            
            # 优化:游戏后期优先探索远离边界的方向
            if game_progress > 0.5:
                # 按距离边界远近排序方向
                dir_with_priority = []
                for dr, dc in dir_values:
                    nr, nc = r + dr, c + dc
                    new_pos = (nr, nc)
                    if (0 <= nr < board and 0 <= nc < board and 
                        new_pos not in body and new_pos not in seen):
                        # 计算到边界的距离作为优先级
                        border_dist = min(nr, board - 1 - nr, nc, board - 1 - nc)
                        dir_with_priority.append((-border_dist, dr, dc))  # 负号使距离大的排在前面
                
                # 按优先级排序
                dir_with_priority.sort()
                directions_to_check = [(dr, dc) for _, dr, dc in dir_with_priority]
            else:
                directions_to_check = dir_values
            
            for dr, dc in directions_to_check:
                nr, nc = r + dr, c + dc
                new_pos = (nr, nc)
                if (0 <= nr < board and 0 <= nc < board and 
                    new_pos not in body and new_pos not in seen):
                    seen.add(new_pos)
                    distance_map[new_pos] = distance_map[(r, c)] + 1
                    q.append(new_pos)
        
        # 优化:提前计算分数所需的关键指标
        seen_size = len(seen)
        if seen_size == 0:
            return 1
        
        # 计算平均距离(优化:避免重复计算)
        avg_distance = sum(distance_map.values()) / seen_size
        
        # 优化边界检测:只计算必要的边界位置
        boundary_count = 0
        border_threshold = 1
        
        # 游戏后期调整边界阈值
        if game_progress > 0.7:
            border_threshold = 2
        
        # 快速边界检测
        for pos in seen:
            if (pos[0] <= border_threshold or pos[0] >= board - border_threshold - 1 or 
                pos[1] <= border_threshold or pos[1] >= board - border_threshold - 1):
                boundary_count += 1
        
        boundary_ratio = boundary_count / seen_size
        
        # 优化评分计算
        if game_progress > 0.6:
            # 游戏后期更看重空间大小和安全性
            safety_factor = 1.0 - boundary_ratio
            return max(1, int(seen_size * 2 * safety_factor))
        else:
            # 综合评分:空间大小 * 平均距离 * (1 - 边界接近度)
            score = seen_size * avg_distance * (1 - boundary_ratio)
            return max(1, score)
    
    # ----------------------------------------------------------------------
    # 🔄 循环检测:避免蛇在小区域内原地绕圈
    # ----------------------------------------------------------------------
    def detect_cycle(pos):
        """优化版循环检测算法,更高效地识别绕圈行为"""
        # 如果蛇很短,不可能形成循环
        if snake_length < 8:  # 降低阈值以便更早检测
            return False
        
        # 获取位置历史记录
        recent_positions = getattr(game, 'recent_positions', None)
        if not recent_positions or len(recent_positions) < 12:  # 降低历史长度要求
            return False
        
        # 优化1:使用集合快速统计唯一位置数量
        recent_10_pos = list(recent_positions)[-10:]
        unique_pos_count = len(set(recent_10_pos))
        
        # 如果唯一位置太少,可能在绕圈
        if unique_pos_count <= 4:  # 更宽松的阈值,提高检测敏感度
            return True
        
        # 优化2:计算最近位置的平均距离(优化计算方式)
        if len(recent_positions) > 15:
            # 只计算最近的8个位置与当前位置的距离
            recent_8_pos = list(recent_positions)[-8:]
            total_dist = 0
            for old_pos in recent_8_pos:
                total_dist += manhattan_dist(pos, old_pos)
            avg_dist = total_dist / 8
            
            # 游戏后期更严格地检测
            threshold = 3.0
            if game_progress > 0.6:
                threshold = 2.5
            
            if avg_dist < threshold:
                return True
        
        # 优化3:检测方向变化模式
        if len(recent_positions) >= 15:
            # 检查是否在进行频繁的U形转弯
            direction_changes = 0
            positions = list(recent_positions)[-15:]
            
            for i in range(2, len(positions)):
                # 计算连续两步的方向
                prev_dir = (positions[i-1][0] - positions[i-2][0], 
                           positions[i-1][1] - positions[i-2][1])
                curr_dir = (positions[i][0] - positions[i-1][0], 
                           positions[i][1] - positions[i-1][1])
                
                # 检查是否反向
                if (prev_dir[0] == -curr_dir[0] and prev_dir[1] == -curr_dir[1]):
                    direction_changes += 1
                    # 如果短时间内多次反向,立即判定为循环
                    if direction_changes >= 2:
                        return True
        
        return False
    
    # 初始化或更新蛇的位置历史记录
    if not hasattr(game, 'recent_positions'):
        game.recent_positions = deque(maxlen=30)  # 减少历史记录长度,节省内存
    game.recent_positions.append(head)
    
    # ----------------------------------------------------------------------
    # 🔍 评估所有可能的移动方向
    # ----------------------------------------------------------------------
    def evaluate_directions():
        direction_scores = {}
        hx, hy = head
        
        for d, (dr, dc) in dirs.items():
            nr, nc = hx + dr, hy + dc
            new_pos = (nr, nc)
            
            # 跳过反向和无效方向
            if d == opposite_dir or not is_valid(new_pos):
                direction_scores[d] = -1
                continue
            
            # 循环惩罚
            if detect_cycle(new_pos):
                cycle_penalty = 0.3  # 降低可能导致循环的方向的评分
            else:
                cycle_penalty = 1.0
            
            # 计算方向评分
            score = 0
            
            # 基础策略评分
            
            # 1. 空间安全评分
            space_score = advanced_flood_fill(new_pos)
            score += space_score * 0.4  # 空间安全权重
            
            # 2. 食物接近度评分
            dist_to_food = manhattan_dist(new_pos, food)
            # 距离越近分数越高,但使用非线性关系
            food_score = 100 / (dist_to_food + 1)
            score += food_score * 0.3  # 食物接近度权重
            
            # 3. 边界远离度评分(越远离边界越安全)
            border_dist = min(nr, board - 1 - nr, nc, board - 1 - nc)
            border_score = border_dist * 10
            score += border_score * 0.2  # 边界远离度权重
            
            # 4. 移动多样性评分(避免一直朝一个方向移动)
            if hasattr(game, 'previous_directions') and len(game.previous_directions) > 3:
                if d == game.previous_directions[-1] == game.previous_directions[-2]:
                    direction_penalty = 0.7  # 连续多次同一方向会被惩罚
                else:
                    direction_penalty = 1.0
            else:
                direction_penalty = 1.0
            
            # 对抗模式特有策略(当is_opponent=True时)
            if is_opponent and player_head:
                
                # 5. 玩家攻击策略:尝试攻击玩家蛇头
                player_attack_bonus = 0
                dist_to_player = manhattan_dist(new_pos, player_head)
                
                # 如果距离玩家蛇头很近,给予攻击奖励
                if dist_to_player <= 2:
                    # 计算是否可以在下一步或两步内攻击到玩家
                    if dist_to_player == 1:
                        player_attack_bonus = 300  # 直接攻击奖励
                    elif dist_to_player == 2:
                        player_attack_bonus = 150  # 接近攻击奖励
                
                # 6. 包围策略:尝试切断玩家蛇的路径
                encircle_bonus = 0
                # 计算玩家蛇的可能移动方向
                if len(player_snake) > 1:
                    player_body_set = player_body
                    # 如果新位置可以切断玩家到食物的路径,给予奖励
                    player_to_food_path, _ = a_star_path(player_head, food)
                    if player_to_food_path and new_pos in [
                        (player_head[0] + dr, player_head[1] + dc) 
                        for dr, dc in dirs.values()
                    ]:
                        encircle_bonus = 100
                
                # 7. 防御策略:避免被玩家包围
                defense_bonus = 0
                # 计算玩家蛇头与对抗蛇头的位置关系
                if len(player_snake) > 5 and dist_to_player < 5:
                    # 检查是否处于被包围的风险
                    if space_score < 20:
                        defense_bonus = 50  # 在被包围风险下优先逃跑
                
                # 8. 食物竞争策略:当食物靠近时优先获取
                food_competition_bonus = 0
                if dist_to_food < manhattan_dist(player_head, food):
                    food_competition_bonus = 80  # 比玩家更接近食物时的奖励
                
                # 9. 避免撞玩家蛇:给予玩家蛇身体更大的避让权重
                avoid_player_penalty = 1.0
                if new_pos in player_body:
                    direction_scores[d] = -1
                    continue
                # 检查下一步是否靠近玩家蛇身体
                for p_pos in player_body:
                    if manhattan_dist(new_pos, p_pos) == 1:
                        avoid_player_penalty = 0.5
                        break
                
                # 根据游戏状态调整权重
                current_weight = 0.1  # 默认权重较低
                
                # 根据分数差距调整攻击性
                player_score = len(player_snake) - 3 if player_snake else 0
                score_diff = score - player_score
                
                if score_diff > 5:  # 对抗蛇领先时,更注重防御
                    current_weight = 0.1
                elif score_diff < -5:  # 对抗蛇落后时,更注重攻击
                    current_weight = 0.3
                else:  # 势均力敌时,平衡策略
                    current_weight = 0.2
                
                # 应用对抗模式策略评分
                score += (player_attack_bonus + encircle_bonus + 
                         defense_bonus + food_competition_bonus) * current_weight
                cycle_penalty *= avoid_player_penalty
            
            # 综合所有评分
            final_score = score * cycle_penalty * direction_penalty
            direction_scores[d] = final_score
        
        return direction_scores
    
    # ----------------------------------------------------------------------
    # � 主决策逻辑
    # ----------------------------------------------------------------------
    # 1. 首先尝试A*找食物路径
    path_to_food, path_length = a_star_path(head, food)
    
    # 如果有到食物的安全路径,且不会导致立即危险
    if path_to_food and path_to_food[0] != opposite_dir:
        # 检查路径第一步是否安全(空间足够)
        hx, hy = head
        dr, dc = dirs[path_to_food[0]]
        next_pos = (hx + dr, hy + dc)
        
        # 计算吃完食物后的预期空间
        # 模拟吃完食物后的身体状态(假设身体变长)
        if hasattr(game, 'simulate_growth'):
            future_space = game.simulate_growth(next_pos)
        else:
            # 简化版:当前空间评估
            future_space = advanced_flood_fill(next_pos)
        
        # 如果吃完食物后仍有足够空间,就去吃
        min_safe_space = max(10, snake_length // 2)  # 最小安全空间
        if future_space > min_safe_space:
            # 记录方向历史
            if not hasattr(game, 'previous_directions'):
                game.previous_directions = deque(maxlen=10)
            game.previous_directions.append(path_to_food[0])
            return path_to_food[0]
    
    # 2. 如果没有直接路径或路径不安全,评估所有方向
    direction_scores = evaluate_directions()
    
    # 找到评分最高的方向
    valid_directions = [(score, d) for d, score in direction_scores.items() if score > 0]
    
    if valid_directions:
        # 按评分排序
        valid_directions.sort(reverse=True, key=lambda x: x[0])
        
        # 选择最高分方向,但添加一些随机性以避免陷入局部最优
        best_score = valid_directions[0][0]
        # 找出所有接近最高分的方向(允许5%的误差)
        candidates = [d for score, d in valid_directions if score >= best_score * 0.95]
        
        # 从候选方向中随机选择(增加探索性)
        chosen_dir = random.choice(candidates)
        
        # 记录方向历史
        if not hasattr(game, 'previous_directions'):
            game.previous_directions = deque(maxlen=10)
        game.previous_directions.append(chosen_dir)
        
        return chosen_dir
    
    # 3. 实在无路:随机选一条不反向的安全路
    safe_moves = []
    for d, (dr, dc) in dirs.items():
        nr, nc = hx + dr, hy + dc
        if is_valid((nr, nc)) and d != opposite_dir:
            safe_moves.append(d)
    
    if safe_moves:
        return random.choice(safe_moves)
    
    # 4. 没路就随机(必死)
    return random.choice([0, 1, 2, 3])


# ---------------------------
# 通用游戏函数
# ---------------------------
# 初始化游戏实例
def init_game(mode="normal"):
    """初始化游戏实例,设置通用配置"""
    seed = random.randint(0, int(1e9))
    game = SnakeGame(
        seed=seed, 
        board_size=game_config["board_size"], 
        silent_mode=False
    )
    # 应用通用配置项
    game.cell_size = game_config["cell_size"]
    game.snake_speed = game_config["snake_speed"]
    game.enable_sound = game_config["enable_sound"]
    game.food_value = game_config["food_value"]
    game.enable_border = game_config["enable_border"]
    game.mode = mode  # 记录当前游戏模式
    return game

# 绘制通用欢迎界面
def draw_welcome_screen(game, title, intro_texts, title_color, title_shadow_color):
    """绘制通用欢迎界面"""
    # 绘制深蓝色渐变背景
    for y in range(game.display_height):
        r = int(0)
        g = int(10)
        b = int(30 - 20 * y / game.display_height)
        pygame.draw.line(game.screen, (r, g, b), (0, y), (game.display_width, y))
        
    center_x = game.display_width // 2
    margin_top = 60  # 顶部边距
    spacing = 30     # 行间距
    btn_margin_top = 50  # 按钮与文字间距

    # 标题 - 使用大字体和指定颜色
    title_surf = game.large_font.render(title, True, title_color)
    title_rect = title_surf.get_rect(center=(center_x, margin_top + title_surf.get_height() // 2))
    
    # 标题阴影效果
    shadow_offset = 2
    shadow_surf = pygame.Surface(title_surf.get_size(), pygame.SRCALPHA)
    shadow_surf.blit(game.large_font.render(title, True, title_shadow_color), (0, 0))
    game.screen.blit(shadow_surf, (title_rect.x + shadow_offset, title_rect.y + shadow_offset))
    game.screen.blit(title_surf, title_rect)

    # 绘制介绍文本
    for i, text in enumerate(intro_texts):
        text_surf = game.font.render(text, True, (200, 200, 200))
        text_rect = text_surf.get_rect(center=(center_x, title_rect.bottom + spacing + i * (text_surf.get_height() + 10)))
        game.screen.blit(text_surf, text_rect)
    
    # START 按钮
    btn_width, btn_height = 200, 60
    btn_rect = pygame.Rect(0, 0, btn_width, btn_height)
    btn_rect.centerx = game.display_width // 2
    btn_rect.top = title_rect.bottom + spacing + len(intro_texts) * (game.font.render("", True, (0,0,0)).get_height() + 10) + btn_margin_top
    
    # 绘制按钮
    pygame.draw.rect(game.screen, title_color, btn_rect, border_radius=10)
    pygame.draw.rect(game.screen, title_shadow_color, btn_rect, 3, border_radius=10)
    
    # 按钮文字
    btn_text = game.font.render("开始游戏", True, (255, 255, 255))
    btn_text_rect = btn_text.get_rect(center=btn_rect.center)
    game.screen.blit(btn_text, btn_text_rect)
    
    # 保存按钮位置用于点击检测
    game.start_button_rect = btn_rect
    pygame.display.flip()

# 处理通用倒计时动画
def handle_countdown(game, countdown_snd, seconds=3):
    """处理倒计时动画"""
    for i in range(seconds, 0, -1):
        game.screen.fill((0, 0, 0))
        cnt_surf = game.large_font.render(str(i), True, (255, 255, 255))
        game.screen.blit(cnt_surf, (game.display_width // 2 - cnt_surf.get_width() // 2,
                                    game.display_height // 2 - cnt_surf.get_height() // 2))
        pygame.display.flip()
        if countdown_snd:
            try:
                countdown_snd.play()
            except: pass  # 静默失败
        pygame.time.wait(700)

# 绘制通用按钮
def draw_button(game, x, y, width, height, text, normal_color, hover_color, border_color, hover_border_color, mouse_pos):
    """绘制按钮的通用函数"""
    button_rect = pygame.Rect(x, y, width, height)
    is_hovered = button_rect.collidepoint(mouse_pos)
    
    # 悬停效果和阴影
    if is_hovered:
        shadow_rect = button_rect.copy()
        shadow_rect.x += 2
        shadow_rect.y += 2
        shadow_surf = pygame.Surface((shadow_rect.width, shadow_rect.height), pygame.SRCALPHA)
        pygame.draw.rect(shadow_surf, (0, 0, 0, 100), (0, 0, shadow_rect.width, shadow_rect.height), border_radius=10)
        game.screen.blit(shadow_surf, (shadow_rect.x, shadow_rect.y))
    
    # 绘制按钮
    pygame.draw.rect(game.screen, hover_color if is_hovered else normal_color, button_rect, border_radius=10)
    pygame.draw.rect(game.screen, hover_border_color if is_hovered else border_color, button_rect, 2, border_radius=10)
    
    # 绘制文本
    btn_text = game.font.render(text, True, (255, 255, 255))
    text_rect = btn_text.get_rect(center=button_rect.center)
    game.screen.blit(btn_text, text_rect)
    
    return button_rect

# 绘制通用游戏结束界面
def draw_game_over_screen(game, mouse_pos, btn_width=200, btn_height=60, btn_spacing=15, btn_margin_top=20):
    """绘制通用游戏结束界面"""
    # 获取游戏区域位置信息
    if hasattr(game, 's_area_x'):
        s_area_y = game.s_area_y
        s_area_height = game.s_area_height
    else:
        s_area_y = 50
        s_area_height = game.display_height - 200
    
    center_x = game.display_width // 2
    y_pos = s_area_y + s_area_height + btn_margin_top
    
    # 使用通用按钮绘制函数
    game.retry_button_rect = draw_button(game, center_x - btn_width//2, y_pos, btn_width, btn_height, 
                              "再来一次", (120, 120, 120), (150, 150, 150), (150, 150, 150), (180, 180, 180), mouse_pos)
    
    y_pos += btn_height + btn_spacing
    game.menu_button_rect = draw_button(game, center_x - btn_width//2, y_pos, btn_width, btn_height, 
                             "返回菜单", (150, 150, 180), (180, 180, 210), (180, 180, 210), (200, 200, 230), mouse_pos)
    
    y_pos += btn_height + btn_spacing
    game.exit_button_rect = draw_button(game, center_x - btn_width//2, y_pos, btn_width, btn_height, 
                             "退出游戏", (220, 70, 70), (250, 100, 100), (180, 50, 50), (230, 80, 80), mouse_pos)

# 处理通用游戏结束界面事件
def handle_game_over_events(game, events):
    """处理游戏结束界面的通用事件"""
    for event in events:
        if event.type == pygame.QUIT or (event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE):
            return "exit"
        elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:  # 左键点击
            if hasattr(game, "retry_button_rect") and game.retry_button_rect.collidepoint(event.pos):
                return "retry"
            elif hasattr(game, "menu_button_rect") and game.menu_button_rect.collidepoint(event.pos):
                return "menu"
            elif hasattr(game, "exit_button_rect") and game.exit_button_rect.collidepoint(event.pos):
                return "exit"
    return None


# ---------------------------
# 各类游戏模式主函数
# ---------------------------

# 普通模式
def main_normal():
    """普通模式主函数:玩家可自行控制或AI接管"""
    game = init_game("normal")
    clock = pygame.time.Clock()
    update_interval = 0.15  # 略微提高游戏更新频率,提升流畅度
    last_update = time.time()
    
    action = -1
    game_state = "welcome"  # 初始游戏状态:欢迎界面
    ai_connected = False    # AI 开关(由右侧按钮控制)
    ai_control = False      # 当前是否由 AI 控制
    countdown_snd = game.sound_count

    # 游戏介绍文本
    intro_texts = [
        "游戏目标: 控制蛇吃到尽可能多的食物,获得高分!",
        "操作说明: 使用方向键(↑↓←→)控制蛇的移动方向",
        "AI功能: 右侧面板可接通/断开AI,AI接通后会自动控制蛇的移动",
        "游戏规则: 撞到墙壁或自己的身体会导致游戏结束",
        "提示: 蛇吃到食物后会变长,移动速度会逐渐增加"
    ]
    
    # 创建绘制欢迎界面的函数,使用通用函数
    def draw_welcome():
        draw_welcome_screen(game, "贪吃蛇游戏 - 多模式AI版本", intro_texts, (0, 255, 0), (0, 100, 0))
    
    # 游戏结束界面背景和信息展示
    def draw_game_over():
        game.screen.fill((0, 0, 0))
        margin_top = 60
        spacing = 40
        btn_margin_top = 30
        btn_spacing = 10

        # 标题
        title = game.large_font.render("游戏结束", True, (255, 255, 255))
        title_rect = title.get_rect(center=(game.display_width // 2, margin_top))
        game.screen.blit(title, title_rect)

        # 分数显示
        score_text = game.font.render(f"最终分数: {game.score}", True, (200, 200, 200))
        score_rect = score_text.get_rect(center=(game.display_width // 2, title_rect.bottom + spacing))
        game.screen.blit(score_text, score_rect)

        # 蛇身长度
        length = len(game.snake)
        length_text = game.font.render(f"蛇身长度: {length} 格", True, (200, 255, 200))
        length_rect = length_text.get_rect(center=(game.display_width // 2, score_rect.bottom + spacing // 2))
        game.screen.blit(length_text, length_rect)



        # 绘制蛇形展示区域
        s_area_width, s_area_height = 400, 300
        s_area_x = (game.display_width - s_area_width) // 2
        s_area_y = length_rect.bottom + 50
        pygame.draw.rect(game.screen, (30, 30, 30), (s_area_x, s_area_y, s_area_width, s_area_height), border_radius=12)

        # ---------------------------
        # 在展示区域绘制蛇(S型折叠)
        # ---------------------------
        cell = 10  # 每个方格像素
        cols = s_area_width // cell
        rows = s_area_height // cell

        # 生成一条“展示用”的S型蛇(不使用原坐标,只展示长度)
        display_snake = []
        direction = 1  # 1 向右, -1 向左
        row = 0
        count = 0

        for i in range(length):
            col = (i % (cols - 2)) + 1 if direction == 1 else (cols - 2 - (i % (cols - 2)))
            display_snake.append((row + 1, col))
            if (i + 1) % (cols - 2) == 0:
                row += 2
                direction *= -1
                if row + 1 >= rows:
                    break  # 超出展示区则停止

        # 绘制蛇头(蓝色菱形)
        if display_snake:
            head_r, head_c = display_snake[0]
            head_x = s_area_x + head_c * cell
            head_y = s_area_y + head_r * cell
            pygame.draw.polygon(game.screen, (100, 100, 255), [
                (head_x + cell // 2, head_y),
                (head_x + cell, head_y + cell // 2),
                (head_x + cell // 2, head_y + cell),
                (head_x, head_y + cell // 2)
            ])
            # 眼睛
            eye_size = 2
            pygame.draw.circle(game.screen, (255, 255, 255), (head_x + 3, head_y + 3), eye_size)
            pygame.draw.circle(game.screen, (255, 255, 255), (head_x + cell - 3, head_y + 3), eye_size)

        # 身体颜色渐变(绿→深绿)- 优化:不使用numpy,使用简单的线性计算
        body_count = max(len(display_snake) - 1, 1)
        for i, (r, c) in enumerate(display_snake[1:], start=0):
            # 简单的线性渐变计算,避免numpy依赖
            green_value = 255 - int((255 - 80) * (i / body_count))
            body_x = s_area_x + c * cell
            body_y = s_area_y + r * cell
            pygame.draw.rect(game.screen, (0, green_value, 0),
                            (body_x, body_y, cell, cell), border_radius=3)



        # 使用通用函数绘制按钮部分,传入特定参数
        game.s_area_x, game.s_area_y, game.s_area_width, game.s_area_height = s_area_x, s_area_y, s_area_width, s_area_height
        draw_game_over_screen(game, pygame.mouse.get_pos(), 200, 50, 15, btn_margin_top)

        pygame.display.flip()

    # 主循环
    running = True
    while running:
        for event in pygame.event.get():
            # 退出
            if event.type == pygame.QUIT:
                running = False
                break

            # 鼠标点击事件
            if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
                # 欢迎界面点击开始按钮
                if game_state == "welcome" and hasattr(game, "start_button_rect"):
                        if game.start_button_rect.collidepoint(event.pos):
                            # 倒计时 1 秒 - 优化:减少重复计算
                            center_x, center_y = game.display_width // 2, game.display_height // 2
                            for i in range(1, 0, -1):
                                game.screen.fill((0, 0, 0))
                                cnt_surf = game.large_font.render(str(i), True, (255, 255, 255))
                                cnt_rect = cnt_surf.get_rect(center=(center_x, center_y))
                                game.screen.blit(cnt_surf, cnt_rect)
                                pygame.display.flip()
                                if countdown_snd:
                                    try:
                                        countdown_snd.play()
                                    except:
                                        pass  # 静默失败
                                pygame.time.wait(700)
                            action = -1
                            game_state = "running"
                            last_update = time.time()

                # 游戏结束界面按钮点击
                elif game_state == "game_over":
                    # 停止背景音乐
                    game.stop_bgm()
                    # 使用通用事件处理函数
                    result = handle_game_over_events(game, [event])
                    if result == "retry":
                        # 使用通用倒计时函数
                        handle_countdown(game, countdown_snd, 1)
                        game.reset()
                        action = -1
                        game_state = "running"
                        last_update = time.time()
                        # 开始播放背景音乐
                        game.play_bgm()
                    elif result == "menu":
                        # 返回菜单
                        pygame.quit()
                        main_gui()
                    elif result == "exit":
                        # 退出游戏
                        pygame.quit()
                        sys.exit()

                # AI 按钮点击
                elif game_state == "running" and hasattr(game, "ai_button_rect"):
                    if game.ai_button_rect.collidepoint(event.pos):
                        ai_connected = not ai_connected
                        ai_control = ai_connected  # 接通AI后立即开始控制

            # 键盘事件(玩家手动控制)
            if event.type == pygame.KEYDOWN and game_state == "running":
                # 玩家控制优先级高于AI控制
                # 当玩家按下方向键时,立即执行移动并重置AI控制标志
                # 同时设置ai_connected = False,使AI状态显示从绿色变为红色
                if event.key == pygame.K_UP:
                    action = 0
                    ai_control = False  # 确保玩家按下方向键时获得控制权
                    ai_connected = False  # 自动禁用AI连接,使状态显示为红色
                elif event.key == pygame.K_LEFT:
                    action = 1
                    ai_control = False
                    ai_connected = False
                elif event.key == pygame.K_RIGHT:
                    action = 2
                    ai_control = False
                    ai_connected = False
                elif event.key == pygame.K_DOWN:
                    action = 3
                    ai_control = False
                    ai_connected = False
                # WASD键控制
                elif event.key == pygame.K_w:
                    action = 0
                    ai_control = False  # 确保玩家按下方向键时获得控制权
                    ai_connected = False  # 自动禁用AI连接,使状态显示为红色
                elif event.key == pygame.K_a:
                    action = 1
                    ai_control = False
                    ai_connected = False
                elif event.key == pygame.K_d:
                    action = 2
                    ai_control = False
                    ai_connected = False
                elif event.key == pygame.K_s:
                    action = 3
                    ai_control = False
                    ai_connected = False
                # 按键后立即执行移动,不等待更新周期
                if event.key in [pygame.K_UP, pygame.K_DOWN, pygame.K_LEFT, pygame.K_RIGHT, 
                                pygame.K_w, pygame.K_s, pygame.K_a, pygame.K_d]:
                    # 立即执行移动
                    done, info = game.step(action)
                    game.render(ai_connected, draw_opponent=False, show_ai=True)
                    # 重置动作,避免连续移动
                    action = -1
                elif event.key == pygame.K_x:
                    # 切换 AI 控制
                    ai_control = not ai_control
                    if ai_control:
                        ai_connected = True

        # 游戏运行状态
        if game_state == "welcome":
            draw_welcome()
            pygame.display.flip()  # 确保欢迎界面正确显示
            clock.tick(20)
            continue
        if game_state == "game_over":
            draw_game_over()
            pygame.display.flip()  # 确保游戏结束界面正确显示
            clock.tick(20)
            continue
        
        # 如果是running状态,确保始终有渲染(即使不在更新间隔)
        if game_state == "running":
            game.render(ai_connected, draw_opponent=False, show_ai=True)
            pygame.display.flip()  # 确保所有渲染内容显示到屏幕

        # 游戏步骤更新
        now = time.time()
        if now - last_update >= update_interval:
            last_update = now  # 更新时间
            
            if game_state == "running":
                # 玩家控制绿色蛇
                # 即使没有新的键盘输入,蛇也会保持当前方向移动
                if ai_connected and ai_control:
                    # 只在AI控制时调用get_ai_action
                    chosen_action = get_ai_action(game, is_opponent=False)
                else:
                    # 对于玩家控制,action为-1时保持当前方向
                    chosen_action = action
                
                # 执行游戏步骤
                done, info = game.step(chosen_action)
                
                # 只有当游戏未结束时才渲染
                if not done:
                    game.render(ai_connected, draw_opponent=False, show_ai=True)
                
                # 重置玩家动作,这样蛇会继续按照当前方向移动
                # 只有当玩家按下方向键时,action才会改变
                action = -1

            # 检查游戏结束状态
            if done:
                game_state = "game_over"
                # 保存游戏结束时间,用于固定显示时长
                game.game_end_time = time.time()
                # 保存游戏结束时间,用于固定显示时长
                game.game_end_time = time.time()
                # 保存游戏结束时间,用于固定显示时长
                game.game_end_time = time.time()
                # 保存游戏结束时间,用于固定显示时长
                game.game_end_time = time.time()
                # 保存游戏结束时间,用于固定显示时长
                game.game_end_time = time.time()
                # 保存游戏结束时间,用于固定显示时长
                game.game_end_time = time.time()

        clock.tick(60)

    pygame.quit()
    sys.exit()

# 影子模式
def main_three_snake():
    """影子模式主函数:玩家控制绿色蛇,AI1和AI2作为影子完全模仿玩家移动"""
    seed = random.randint(0, int(1e9))
    # 使用全局游戏配置初始化游戏
    game = SnakeGame(
        seed=seed, 
        board_size=game_config["board_size"], 
        silent_mode=False
    )
    # 应用其他配置项
    game.cell_size = game_config["cell_size"]
    game.snake_speed = game_config["snake_speed"]
    game.enable_sound = game_config["enable_sound"]
    game.food_value = game_config["food_value"]
    game.enable_border = game_config["enable_border"]

    # 初始化影子模式游戏状态
    game.reset_three_snake_mode()

    # 初始化
    clock = pygame.time.Clock()
    update_interval = 0.2  # 游戏更新间隔(秒)
    last_update = time.time()

    action = -1
    game_state = "welcome"  # 初始游戏状态:欢迎界面
    countdown_snd = game.sound_count
    
    # 绘制欢迎界面的函数
    def draw_welcome():
        # 绘制深蓝色渐变背景
        for y in range(game.display_height):
            r = int(0)
            g = int(10)
            b = int(30 - 20 * y / game.display_height)
            pygame.draw.line(game.screen, (r, g, b), (0, y), (game.display_width, y))
            
        center_x = game.display_width // 2
        margin_top = 60  # 顶部边距
        spacing = 30     # 行间距
        btn_margin_top = 50  # 按钮与文字间距

        # 标题 - 使用大字体和紫色(影子模式主题色)
        title = game.large_font.render("贪吃蛇游戏 - 影子模式", True, (220, 70, 220))
        title_rect = title.get_rect(center=(center_x, margin_top + title.get_height() // 2))
        
        # 标题阴影效果
        shadow_offset = 2
        shadow_surf = pygame.Surface(title.get_size())
        shadow_surf.fill((0, 0, 0, 0))
        shadow_surf.blit(game.large_font.render("贪吃蛇游戏 - 影子模式", True, (180, 50, 180)), (0, 0))
        game.screen.blit(shadow_surf, (title_rect.x + shadow_offset, title_rect.y + shadow_offset))
        game.screen.blit(title, title_rect)

        # 游戏介绍文本
        intro_texts = [
            "游戏目标: 控制绿色蛇,AI蛇作为影子完全模仿你的移动!",
            "操作说明: 使用方向键(↑↓←→)或WASD控制蛇的移动方向",
            "注意: AI蛇死亡玩家也会死亡,所有蛇同步增长蛇身!"
        ]
        
        # 绘制介绍文本
        for i, text in enumerate(intro_texts):
            text_surf = game.font.render(text, True, (200, 200, 200))
            text_rect = text_surf.get_rect(center=(center_x, title_rect.bottom + spacing + i * (text_surf.get_height() + 10)))
            game.screen.blit(text_surf, text_rect)
        
        # START 按钮
        btn_width, btn_height = 200, 60
        btn_rect = pygame.Rect(0, 0, btn_width, btn_height)
        btn_rect.centerx = game.display_width // 2
        btn_rect.top = title_rect.bottom + spacing + len(intro_texts) * (game.font.render("", True, (0,0,0)).get_height() + 10) + btn_margin_top
        
        # 绘制按钮
        pygame.draw.rect(game.screen, (220, 70, 220), btn_rect, border_radius=10)
        pygame.draw.rect(game.screen, (180, 50, 180), btn_rect, 3, border_radius=10)
        
        # 按钮文字
        btn_text = game.font.render("开始游戏", True, (255, 255, 255))
        btn_text_rect = btn_text.get_rect(center=btn_rect.center)
        game.screen.blit(btn_text, btn_text_rect)
        
        # 保存按钮位置用于点击检测
        game.start_button_rect = btn_rect
    
    # 主游戏循环 - 统一处理所有游戏状态
    while True:
        current_time = time.time()
        
        # 事件处理 - 对所有状态通用
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            
            # 欢迎界面事件处理
            if game_state == "welcome":
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_RETURN or event.key == pygame.K_KP_ENTER:
                        game_state = "running"
                        if countdown_snd:
                            try:
                                countdown_snd.play()
                            except Exception:
                                pass
                        last_update = time.time()
                elif event.type == pygame.MOUSEBUTTONDOWN:
                    # 检测开始按钮点击
                    if hasattr(game, 'start_button_rect') and game.start_button_rect.collidepoint(event.pos):
                        game_state = "running"
                        if countdown_snd:
                            try:
                                countdown_snd.play()
                            except Exception:
                                pass
                        last_update = time.time()
            
            # 游戏运行状态事件处理
            elif game_state == "running":
                if event.type == pygame.KEYDOWN:
                    # 方向控制
                    if event.key in [pygame.K_UP, pygame.K_w]:
                        action = 0  # UP
                    elif event.key in [pygame.K_LEFT, pygame.K_a]:
                        action = 1  # LEFT
                    elif event.key in [pygame.K_RIGHT, pygame.K_d]:
                        action = 2  # RIGHT
                    elif event.key in [pygame.K_DOWN, pygame.K_s]:
                        action = 3  # DOWN
                    elif event.key == pygame.K_ESCAPE:
                        pygame.quit()
                        main_gui()
                        return
            
            # 游戏结束界面事件处理
            elif game_state == "game_over":
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_r or event.key == pygame.K_KP_ENTER:
                        # 重新开始
                        game.reset_three_snake_mode()
                        game_state = "running"
                        action = -1  # 重置动作
                        last_update = time.time()
                    elif event.key == pygame.K_m:
                        # 返回菜单
                        pygame.quit()
                        main_gui()
                        return
                    elif event.key == pygame.K_ESCAPE:
                        pygame.quit()
                        sys.exit()
                elif event.type == pygame.MOUSEBUTTONDOWN:
                    # 检测重试按钮点击 - 使用与draw_game_over_screen方法中完全相同的位置计算
                    button_width = 200
                    button_height = 60
                    button_y = game.display_height // 2
                    btn_spacing = 10  # 与draw_game_over_screen方法中使用的值一致
                    
                    retry_button_rect = pygame.Rect(
                        (game.display_width - button_width) // 2,
                        button_y,
                        button_width,
                        button_height
                    )
                    # 检测菜单按钮点击
                    menu_button_rect = pygame.Rect(
                        (game.display_width - button_width) // 2,
                        button_y + button_height + btn_spacing,
                        button_width,
                        button_height
                    )
                    # 检测退出按钮点击
                    exit_button_rect = pygame.Rect(
                        (game.display_width - button_width) // 2,
                        button_y + 2 * (button_height + btn_spacing),
                        button_width,
                        button_height
                    )
                    if retry_button_rect.collidepoint(event.pos):
                        game.reset_three_snake_mode()
                        game_state = "running"
                        action = -1  # 重置动作
                        last_update = time.time()
                    elif menu_button_rect.collidepoint(event.pos):
                        pygame.quit()
                        main_gui()
                        return
                    elif exit_button_rect.collidepoint(event.pos):
                        pygame.quit()
                        sys.exit()
        
        # 根据当前游戏状态执行相应逻辑
        if game_state == "welcome":
            # 绘制欢迎界面
            draw_welcome()
            pygame.display.flip()
        
        elif game_state == "running":
            # 游戏逻辑更新
            if current_time - last_update >= update_interval:
                done, info = game.step_three_snake_mode(action)
                action = -1  # 重置动作
                last_update = current_time
                
                if done:
                    game_state = "game_over"
            
            # 绘制游戏界面
            game.draw_board()
            pygame.display.flip()
        
        elif game_state == "game_over":
            # 绘制游戏结束界面
            game.draw_game_over_screen()
            pygame.display.flip()
        
        # 控制帧率
        clock.tick(60)

# 对抗模式
def main_opponent():
    """对抗模式主函数:玩家控制绿色蛇,AI控制红色蛇"""
    seed = random.randint(0, int(1e9))
    # 使用全局游戏配置初始化游戏
    game = SnakeGame(
        seed=seed, 
        board_size=game_config["board_size"], 
        silent_mode=False
    )
    # 应用其他配置项
    game.cell_size = game_config["cell_size"]
    game.snake_speed = game_config["snake_speed"]
    game.enable_sound = game_config["enable_sound"]
    game.food_value = game_config["food_value"]
    game.enable_border = game_config["enable_border"]

    # 初始化对抗模式游戏状态
    game.reset_opponent_mode()

    # 初始化
    clock = pygame.time.Clock()
    update_interval = 0.2  # 游戏更新间隔(秒)
    last_update = time.time()

    action = -1
    game_state = "welcome"  # 初始游戏状态:欢迎界面
    countdown_snd = game.sound_count

    # 欢迎界面
    def draw_welcome():
        game.screen.fill((0, 0, 0))
        margin_top = 50  # 顶部边距
        spacing = 40     # 行间距
        btn_margin_top = 60  # 按钮与文字间距

        # 标题
        title = game.large_font.render("对抗模式", True, (255, 255, 255))
        title_rect = title.get_rect(center=(game.display_width // 2, margin_top + title.get_height() // 2))
        game.screen.blit(title, title_rect)

        # 信息文本
        info1 = game.font.render("方向键或WASD控制绿色蛇(↑↓←→ / W A S D)", True, (200, 200, 200))
        info2 = game.font.render("小心红色AI蛇!碰到就会死亡!", True, (200, 200, 200))
        info3 = game.font.render("目标:达到1000积分!", True, (200, 200, 200))
        game.screen.blit(info1, (game.display_width // 2 - info1.get_width() // 2, title_rect.bottom + spacing))
        game.screen.blit(info2, (game.display_width // 2 - info2.get_width() // 2, title_rect.bottom + spacing + info1.get_height() + 5))
        game.screen.blit(info3, (game.display_width // 2 - info3.get_width() // 2, title_rect.bottom + spacing + info1.get_height() + info2.get_height() + 10))

        # START 按钮
        btn_width, btn_height = 140, 40
        btn_rect = pygame.Rect(0, 0, btn_width, btn_height)
        btn_rect.centerx = game.display_width // 2
        btn_rect.top = title_rect.bottom + spacing + info1.get_height() + info2.get_height() + info3.get_height() + btn_margin_top
        pygame.draw.rect(game.screen, (100, 100, 100), btn_rect, border_radius=6)

        text_s = game.font.render("开始游戏", True, (255, 255, 255))
        text_rect = text_s.get_rect(center=btn_rect.center)
        game.screen.blit(text_s, text_rect)

        game.start_button_rect = btn_rect
        pygame.display.flip()

    # 游戏结束界面
    def draw_game_over():
        # 绘制深蓝色渐变背景
        for y in range(game.display_height):
            r = int(0)
            g = int(10)
            b = int(30 - 20 * y / game.display_height)
            pygame.draw.line(game.screen, (r, g, b), (0, y), (game.display_width, y))
            
        margin_top = 60
        spacing = 35
        btn_margin_top = 25

        # 标题 - 根据分数显示不同内容和颜色
        if game.score >= 1000:
            title_text = "恭喜胜利!"
            title_color = (255, 255, 100)  # 金黄色标题
            shadow_color = (180, 180, 0)   # 深黄色阴影
        else:
            title_text = "游戏结束"
            title_color = (255, 255, 255)  # 白色标题
            shadow_color = (150, 150, 150) # 灰色阴影
            
        # 标题阴影效果
        title_shadow = game.large_font.render(title_text, True, shadow_color)
        title = game.large_font.render(title_text, True, title_color)
        title_rect = title.get_rect(center=(game.display_width // 2, margin_top))
        
        # 绘制阴影和标题
        shadow_offset = 2
        game.screen.blit(title_shadow, (title_rect.x + shadow_offset, title_rect.y + shadow_offset))
        game.screen.blit(title, title_rect)

        # 分数显示 - 使用更醒目的颜色和更大的字体
        score_text = game.font.render(f"最终分数: {game.score}", True, (255, 255, 150))
        score_rect = score_text.get_rect(center=(game.display_width // 2, title_rect.bottom + spacing))
        
        # 分数阴影效果
        score_shadow = game.font.render(f"最终分数: {game.score}", True, (150, 150, 50))
        game.screen.blit(score_shadow, (score_rect.x + 1, score_rect.y + 1))
        game.screen.blit(score_text, score_rect)

        # 蛇身长度 - 使用绿色系
        length = len(game.snake)
        length_text = game.font.render(f"蛇身长度: {length} 格", True, (150, 255, 150))
        length_rect = length_text.get_rect(center=(game.display_width // 2, score_rect.bottom + spacing // 2))
        game.screen.blit(length_text, length_rect)
        
        # 计算游戏时长统计
        stats_text = ""
        stats_rect = None
        if hasattr(game, 'game_start_time'):
            # 使用固定的结束时间计算时长,避免游戏结束后时长继续增加
            if hasattr(game, 'game_end_time'):
                game_duration = game.game_end_time - game.game_start_time
            else:
                game_duration = time.time() - game.game_start_time
            minutes = int(game_duration // 60)
            seconds = int(game_duration % 60)
            stats_text = f"游戏时长: {minutes}分{seconds}秒"
            stats_surf = game.font.render(stats_text, True, (200, 200, 255))
            stats_rect = stats_surf.get_rect(center=(game.display_width // 2, length_rect.bottom + spacing // 2))
            game.screen.blit(stats_surf, stats_rect)

        # 死亡原因 - 使用红色系突出显示
        reason_rect = None
        if hasattr(game, 'death_reason') and game.death_reason:
            reason_text = game.font.render(f"死亡原因: {game.death_reason}", True, (255, 150, 150))
            # 根据前面是否有统计信息调整位置
            if stats_rect:
                reason_rect = reason_text.get_rect(center=(game.display_width // 2, stats_rect.bottom + spacing // 2))
            else:
                reason_rect = reason_text.get_rect(center=(game.display_width // 2, length_rect.bottom + spacing // 2))
            game.screen.blit(reason_text, reason_rect)

        # 绘制蛇形展示区域 - 添加边框和背景美化
        s_area_width, s_area_height = 400, 300
        s_area_x = (game.display_width - s_area_width) // 2
        
        # 根据前面元素的位置确定起始Y坐标
        if reason_rect:
            s_area_y = reason_rect.bottom + 40
        elif stats_rect:
            s_area_y = stats_rect.bottom + 40
        else:
            s_area_y = length_rect.bottom + 40
            
        # 绘制带边框的展示区域
        pygame.draw.rect(game.screen, (60, 60, 60), (s_area_x, s_area_y, s_area_width, s_area_height), border_radius=12)
        pygame.draw.rect(game.screen, (40, 40, 40), (s_area_x + 1, s_area_y + 1, s_area_width - 2, s_area_height - 2), border_radius=11)
        pygame.draw.rect(game.screen, (70, 70, 70), (s_area_x, s_area_y, s_area_width, s_area_height), 1, border_radius=12)

        # ---------------------------
        # 在展示区域绘制蛇(S型折叠)
        # ---------------------------
        cell = 10  # 每个方格像素
        cols = s_area_width // cell
        rows = s_area_height // cell

        # 生成一条"展示用"的S型蛇(不使用原坐标,只展示长度)
        display_snake = []
        direction = 1  # 1 向右, -1 向左
        row = 0

        for i in range(length):
            col = (i % (cols - 2)) + 1 if direction == 1 else (cols - 2 - (i % (cols - 2)))
            display_snake.append((row + 1, col))
            if (i + 1) % (cols - 2) == 0:
                row += 2
                direction *= -1
                if row + 1 >= rows:
                    break  # 超出展示区则停止

        # 绘制蛇头(使用更醒目的蓝色)
        if display_snake:
            head_r, head_c = display_snake[0]
            head_x = s_area_x + head_c * cell
            head_y = s_area_y + head_r * cell
            pygame.draw.polygon(game.screen, (120, 120, 255), [
                (head_x + cell // 2, head_y),
                (head_x + cell, head_y + cell // 2),
                (head_x + cell // 2, head_y + cell),
                (head_x, head_y + cell // 2)
            ])
            # 眼睛 - 使用更亮的颜色
            eye_size = 2
            pygame.draw.circle(game.screen, (255, 255, 255), (head_x + 3, head_y + 3), eye_size)
            pygame.draw.circle(game.screen, (255, 255, 255), (head_x + cell - 3, head_y + 3), eye_size)

        # 身体颜色渐变(更平滑的绿色到深绿色)
        color_list = np.linspace(255, 50, max(len(display_snake) - 1, 1), dtype=np.uint8)
        for i, (r, c) in enumerate(display_snake[1:], start=0):
            body_x = s_area_x + c * cell
            body_y = s_area_y + r * cell
            # 使用更平滑的圆角矩形
            pygame.draw.rect(game.screen, (0, int(color_list[i]), 0),
                            (body_x, body_y, cell, cell), border_radius=4)

        # 使用通用函数绘制按钮部分
        game.s_area_x, game.s_area_y, game.s_area_width, game.s_area_height = s_area_x, s_area_y, s_area_width, s_area_height
        draw_game_over_screen(game, pygame.mouse.get_pos(), 200, 50, 15, btn_margin_top)
        pygame.display.flip()

    # 主循环
    running = True
    while running:
        for event in pygame.event.get():
            # 退出
            if event.type == pygame.QUIT:
                running = False
                break

            # 鼠标点击事件
            if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
                # 欢迎界面点击开始按钮
                if game_state == "welcome" and hasattr(game, "start_button_rect"):
                    if game.start_button_rect.collidepoint(event.pos):
                        # 倒计时 1 秒
                        for i in range(1, 0, -1):
                            game.screen.fill((0, 0, 0))
                            cnt_surf = game.large_font.render(str(i), True, (255, 255, 255))
                            game.screen.blit(cnt_surf, (game.display_width // 2 - cnt_surf.get_width() // 2,
                                                        game.display_height // 2 - cnt_surf.get_height() // 2))
                            pygame.display.flip()
                            if countdown_snd:
                                try:
                                    countdown_snd.play()
                                except:
                                    pass
                            pygame.time.wait(700)
                        action = -1
                        game_state = "running"
                        last_update = time.time()

                # 游戏结束界面按钮点击
                elif game_state == "game_over":
                    # 使用通用事件处理函数
                    result = handle_game_over_events(game, [event])
                    if result == "retry":
                        # 使用通用倒计时函数
                        handle_countdown(game, countdown_snd, 1)
                        game.reset_opponent_mode()  # 使用对抗模式专用的重置方法
                        action = -1
                        game_state = "running"
                        last_update = time.time()
                        # 开始播放背景音乐
                        game.play_bgm()
                    elif result == "menu":
                        # 返回菜单
                        pygame.quit()
                        main_gui()
                    elif result == "exit":
                        # 退出游戏
                        pygame.quit()
                        sys.exit()

            # 键盘事件(玩家手动控制)
            if event.type == pygame.KEYDOWN and game_state == "running":
                # 修复重复的键位检查
                if event.key == pygame.K_UP or event.key == pygame.K_w:
                    action = 0
                elif event.key == pygame.K_LEFT or event.key == pygame.K_a:
                    action = 1
                elif event.key == pygame.K_RIGHT or event.key == pygame.K_d:
                    action = 2
                elif event.key == pygame.K_DOWN or event.key == pygame.K_s:
                    action = 3
                    
                # 按键后立即执行移动,不等待更新间隔
                if action != -1:
                    # 立即执行玩家动作
                    game.step_opponent_mode(action)
                    # 立即渲染画面
                    game.render(ai_connected=False, draw_opponent=True, show_ai=False)
                    # 重置动作以避免连续移动
                    action = -1

        # 游戏运行状态
        if game_state == "welcome":
            draw_welcome()
            pygame.display.flip()  # 确保欢迎界面内容显示
            clock.tick(20)
            continue
        if game_state == "game_over":
            draw_game_over()
            pygame.display.flip()  # 确保游戏结束界面内容显示
            clock.tick(20)
            continue

        # 游戏步骤更新
        now = time.time()
        if now - last_update >= update_interval:
            last_update = now  # 更新时间
            
            if game_state == "running":
                # 玩家控制绿色蛇 - 优化:直接使用action变量,减少中间变量
                done, info = game.step_opponent_mode(action)

                # 对抗模式下AI控制红色蛇
                if not game.opponent_dead:
                    opponent_action = get_ai_action(game, is_opponent=True)
                    done_opponent, _ = game.opponent_step(opponent_action)
                    
                    # 如果对抗蛇死亡,重新部署
                    if done_opponent:
                        # 延迟一小段时间再重新部署,让玩家能看到死亡效果
                        pygame.time.wait(500)
                        game.respawn_opponent()

                # 只有当游戏未结束时才渲染
                if not done:
                    game.render(ai_connected=False, draw_opponent=True, show_ai=False)
                
                # 重置玩家动作
                action = -1

                # 检查胜利条件(1000积分)
                if game.score >= 1000:
                    game_state = "game_over"
                    # 保存游戏结束时间,用于固定显示时长
                    game.game_end_time = time.time()

            # 检查游戏是否结束
            if done:
                game_state = "game_over"
                # 保存游戏结束时间,用于固定显示时长
                game.game_end_time = time.time()

        clock.tick(60)

    pygame.quit()
    sys.exit()

# 限时模式
def main_timed():
    """限时模式主函数:在规定时间内尽可能获得高分"""
    seed = random.randint(0, int(1e9))
    # 使用全局游戏配置初始化游戏
    game = SnakeGame(
        seed=seed, 
        board_size=game_config["board_size"], 
        silent_mode=False
    )
    # 应用其他配置项
    game.cell_size = game_config["cell_size"]
    game.snake_speed = game_config["snake_speed"]
    game.enable_sound = game_config["enable_sound"]
    game.food_value = game_config["food_value"]
    game.enable_border = game_config["enable_border"]

    # 初始化
    clock = pygame.time.Clock()
    update_interval = 0.15  # 略微提高游戏更新频率,提升流畅度
    last_update = time.time()
    
    # 限时模式特有设置
    time_limit = 60  # 60秒时间限制
    start_time = time.time()
    
    # 预加载按钮文本
    start_button_text = "开始游戏"
    retry_button_text = "再来一次"

    action = -1
    game_state = "welcome"  # 初始游戏状态:欢迎界面
    ai_connected = False    # AI 开关(由右侧按钮控制)
    ai_control = False      # 当前是否由 AI 控制
    countdown_snd = game.sound_count

    # 画面上用于鼠标点击检测的隐藏文本
    start_button_surf = game.font.render("START", True, (0, 0, 0))
    retry_button_surf = game.font.render("RETRY", True, (0, 0, 0))

    def draw_welcome():
        # 绘制深蓝色渐变背景
        for y in range(game.display_height):
            r = int(0)
            g = int(10)
            b = int(30 - 20 * y / game.display_height)
            pygame.draw.line(game.screen, (r, g, b), (0, y), (game.display_width, y))
            
        center_x = game.display_width // 2
        margin_top = 60  # 顶部边距
        spacing = 30     # 行间距
        btn_margin_top = 50  # 按钮与文字间距

        # 标题 - 使用大字体和黄色(限时模式主题色)
        title = game.large_font.render("贪吃蛇游戏 - 限时模式", True, (255, 215, 0))
        title_rect = title.get_rect(center=(center_x, margin_top + title.get_height() // 2))
        
        # 标题阴影效果
        shadow_offset = 2
        shadow_surf = pygame.Surface(title.get_size())
        shadow_surf.fill((0, 0, 0, 0))
        shadow_surf.blit(game.large_font.render("贪吃蛇游戏 - 限时模式", True, (200, 180, 0)), (0, 0))
        game.screen.blit(shadow_surf, (title_rect.x + shadow_offset, title_rect.y + shadow_offset))
        game.screen.blit(title, title_rect)

        # 游戏介绍文本
        intro_texts = [
            "游戏目标: 在60秒内吃到尽可能多的食物,获得高分!",
            "操作说明: 使用方向键(↑↓←→)或WASD控制蛇的移动方向",
            "AI功能: 右侧面板可接通/断开AI,AI接通后会自动控制蛇的移动",
            "游戏规则: 撞到墙壁或自己的身体会导致游戏结束",
            "提示: 蛇吃到食物后会变长,移动速度会逐渐增加"
        ]
        
        # 计算位置一次并复用
        text_y = title_rect.bottom + spacing
        
        # 绘制所有介绍文本,使用不同颜色增强可读性
        for i, text_content in enumerate(intro_texts):
            if i == 0:  # 标题行使用高亮颜色
                text_color = (255, 255, 0)
            else:  # 其他行使用白色/浅灰色
                text_color = (200, 200, 200)
            
            info_text = game.font.render(text_content, True, text_color)
            game.screen.blit(info_text, (center_x - info_text.get_width() // 2, text_y))
            text_y += info_text.get_height() + 5

        # START 按钮 - 增强视觉效果
        btn_width, btn_height = 180, 50
        btn_rect = pygame.Rect(0, 0, btn_width, btn_height)
        btn_rect.centerx = center_x
        btn_rect.top = text_y + btn_margin_top
        
        # 按钮悬停效果检测
        mouse_pos = pygame.mouse.get_pos()
        is_hovered = btn_rect.collidepoint(mouse_pos)
        
        # 绘制按钮背景 - 根据悬停状态改变颜色
        btn_color = (220, 180, 70) if is_hovered else (200, 160, 50)  # 黄色系按钮
        pygame.draw.rect(game.screen, btn_color, btn_rect, border_radius=8)
        pygame.draw.rect(game.screen, (180, 140, 30), btn_rect, 3, border_radius=8)
        
        # 如果悬停,添加轻微的阴影效果
        if is_hovered:
            shadow_offset = 2
            shadow_rect = btn_rect.copy()
            shadow_rect.x += shadow_offset
            shadow_rect.y += shadow_offset
            # 使用半透明黑色
            shadow_surf = pygame.Surface((shadow_rect.width, shadow_rect.height), pygame.SRCALPHA)
            pygame.draw.rect(shadow_surf, (0, 0, 0, 100), (0, 0, shadow_rect.width, shadow_rect.height), border_radius=8)
            game.screen.blit(shadow_surf, (shadow_rect.x, shadow_rect.y))
        
        # 按钮文字
        text_s = game.font.render(start_button_text, True, (0, 0, 0))
        text_rect = text_s.get_rect(center=btn_rect.center)
        game.screen.blit(text_s, text_rect)
        
        # 保存按钮位置以供后续检测
        game.start_button_rect = btn_rect
        
        # 刷新屏幕显示
        pygame.display.flip()

    def draw_game_over():
        # 绘制渐变背景(红黑渐变)
        for y in range(game.display_height):
            # 从黑色到深红色的渐变
            r = int(50 + 150 * y / game.display_height)
            g = int(0)
            b = int(0)
            pygame.draw.line(game.screen, (r, g, b), (0, y), (game.display_width, y))
        
        center_x = game.display_width // 2
        margin_top = 80
        spacing = 30
        
        # 游戏结束标题
        title = game.large_font.render("时间到!", True, (255, 215, 0))  # 金色标题
        title_rect = title.get_rect(center=(center_x, margin_top))
        
        # 添加标题阴影
        shadow_surf = pygame.Surface(title.get_size())
        shadow_surf.fill((0, 0, 0, 0))
        shadow_surf.blit(game.large_font.render("时间到!", True, (200, 180, 0)), (0, 0))
        game.screen.blit(shadow_surf, (title_rect.x + 2, title_rect.y + 2))
        game.screen.blit(title, title_rect)
        
        # 显示分数信息
        score_text = game.font.render(f"最终得分: {game.score}", True, (255, 255, 255))
        score_rect = score_text.get_rect(center=(center_x, title_rect.bottom + spacing))
        game.screen.blit(score_text, score_rect)
        
        # 显示蛇身长度
        length_text = game.font.render(f"蛇身长度: {len(game.snake)}", True, (255, 255, 255))
        length_rect = length_text.get_rect(center=(center_x, score_rect.bottom + spacing // 2))
        game.screen.blit(length_text, length_rect)
        
        # 显示游戏时长
        elapsed_time = min(time_limit, time.time() - start_time)
        time_text = game.font.render(f"游戏时长: {int(elapsed_time)}秒", True, (255, 255, 255))
        time_rect = time_text.get_rect(center=(center_x, length_rect.bottom + spacing // 2))
        game.screen.blit(time_text, time_rect)
        
        # 显示死亡原因
        if hasattr(game, 'death_reason') and game.death_reason:
            reason_text = game.font.render(f"{game.death_reason}", True, (255, 100, 100))
            reason_rect = reason_text.get_rect(center=(center_x, time_rect.bottom + spacing))
            game.screen.blit(reason_text, reason_rect)
        
        # 绘制分数统计面板
        stats_panel_y = time_rect.bottom + spacing * 2
        panel_width, panel_height = 400, 150
        panel_rect = pygame.Rect(0, 0, panel_width, panel_height)
        panel_rect.centerx = center_x
        panel_rect.y = stats_panel_y
        
        # 面板背景(半透明)
        s = pygame.Surface((panel_width, panel_height), pygame.SRCALPHA)
        s.fill((0, 0, 0, 180))
        game.screen.blit(s, panel_rect)
        pygame.draw.rect(game.screen, (255, 215, 0), panel_rect, 2, border_radius=10)
        
        # 绘制按钮
        btn_width, btn_height = 150, 45
        btn_spacing = 20
        
        retry_button_rect = pygame.Rect(0, 0, btn_width, btn_height)
        retry_button_rect.centerx = center_x - (btn_width + btn_spacing) // 2
        retry_button_rect.bottom = panel_rect.bottom - 20
        
        menu_button_rect = pygame.Rect(0, 0, btn_width, btn_height)
        menu_button_rect.centerx = center_x + (btn_width + btn_spacing) // 2
        menu_button_rect.bottom = panel_rect.bottom - 20
        
        # 检测按钮悬停
        mouse_pos = pygame.mouse.get_pos()
        retry_hover = retry_button_rect.collidepoint(mouse_pos)
        menu_hover = menu_button_rect.collidepoint(mouse_pos)
        
        # 绘制重试按钮
        retry_color = (220, 180, 70) if retry_hover else (200, 160, 50)
        pygame.draw.rect(game.screen, retry_color, retry_button_rect, border_radius=8)
        pygame.draw.rect(game.screen, (180, 140, 30), retry_button_rect, 2, border_radius=8)
        
        # 绘制返回菜单按钮
        menu_color = (120, 120, 220) if menu_hover else (100, 100, 200)
        pygame.draw.rect(game.screen, menu_color, menu_button_rect, border_radius=8)
        pygame.draw.rect(game.screen, (80, 80, 200), menu_button_rect, 2, border_radius=8)
        
        # 按钮文字
        retry_text = game.font.render(retry_button_text, True, (0, 0, 0))
        retry_text_rect = retry_text.get_rect(center=retry_button_rect.center)
        game.screen.blit(retry_text, retry_text_rect)
        
        menu_text = game.font.render("返回菜单", True, (0, 0, 0))
        menu_text_rect = menu_text.get_rect(center=menu_button_rect.center)
        game.screen.blit(menu_text, menu_text_rect)
        
        # 保存按钮位置
        game.retry_button_rect = retry_button_rect
        game.menu_button_rect = menu_button_rect
        game.exit_button_rect = pygame.Rect(0, 0, 1, 1)  # 占位,实际不使用
        
        # 刷新屏幕显示
        pygame.display.flip()

    # 主循环
    while True:
        # 检查是否超时
        if game_state == "running":
            elapsed_time = time.time() - start_time
            if elapsed_time >= time_limit:
                game_state = "game_over"
                # 设置超时死亡原因
                game.death_reason = "时间到!游戏结束。"
                # 保存游戏结束时间,用于固定显示时长
                game.game_end_time = time.time()
        
        # 事件处理
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            
            # 欢迎界面 - 检查开始按钮点击
            if game_state == "welcome" and event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
                if hasattr(game, 'start_button_rect') and game.start_button_rect.collidepoint(event.pos):
                    game_state = "running"
                    start_time = time.time()  # 重置开始时间
                    game.reset()
                    # 立即渲染初始画面,防止黑屏
                    game.render(ai_connected, draw_opponent=False, show_ai=True)
                    remaining_time = max(0, time_limit - (time.time() - start_time))
                    time_text = game.font.render(f"时间: {int(remaining_time)}秒", True, (255, 215, 0))
                    time_rect = time_text.get_rect(topright=(game.display_width - 20, 20))
                    bg_rect = pygame.Rect(0, 0, time_rect.width + 10, time_rect.height + 5)
                    bg_rect.topleft = (time_rect.left - 5, time_rect.top - 2)
                    pygame.draw.rect(game.screen, (0, 0, 0, 180), bg_rect)
                    pygame.draw.rect(game.screen, (255, 215, 0), bg_rect, 1)
                    game.screen.blit(time_text, time_rect)
                    pygame.display.flip()
            
            # 游戏结束界面 - 检查按钮点击
            elif game_state == "game_over" and event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
                if hasattr(game, 'retry_button_rect') and game.retry_button_rect.collidepoint(event.pos):
                    # 重新开始游戏
                    game.reset()
                    start_time = time.time()
                    game_state = "running"
                elif hasattr(game, 'menu_button_rect') and game.menu_button_rect.collidepoint(event.pos):
                    # 返回主菜单
                    pygame.quit()
                    main_gui()
            
            # 键盘事件(游戏运行状态)
            elif event.type == pygame.KEYDOWN and game_state == "running":
                if event.key == pygame.K_UP or event.key == pygame.K_w:
                    action = 0
                elif event.key == pygame.K_LEFT or event.key == pygame.K_a:
                    action = 1
                elif event.key == pygame.K_RIGHT or event.key == pygame.K_d:
                    action = 2
                elif event.key == pygame.K_DOWN or event.key == pygame.K_s:
                    action = 3
                elif event.key == pygame.K_x:
                    # 切换 AI 控制
                    ai_control = not ai_control
                    if ai_control:
                        ai_connected = True

        # 游戏运行状态
        if game_state == "welcome":
            draw_welcome()
            pygame.display.flip()  # 确保欢迎界面内容显示
            clock.tick(20)
            continue
        if game_state == "game_over":
            draw_game_over()
            pygame.display.flip()  # 确保游戏结束界面内容显示
            clock.tick(20)
            continue

        # 游戏步骤更新
        now = time.time()
        if now - last_update >= update_interval:
            last_update = now  # 更新时间
            
            if game_state == "running":
                # 玩家控制绿色蛇
                # 即使没有新的键盘输入,蛇也会保持当前方向移动
                if ai_connected and ai_control:
                    # 只在AI控制时调用get_ai_action
                    chosen_action = get_ai_action(game, is_opponent=False)
                else:
                    # 对于玩家控制,action为-1时保持当前方向
                    chosen_action = action
                
                # 执行游戏步骤
                done, info = game.step(chosen_action)
                
                # 只有当游戏未结束时才渲染
                if not done:
                    # 绘制游戏画面,包括剩余时间
                    game.render(ai_connected, draw_opponent=False, show_ai=True)
                    
                    # 在右上角显示剩余时间
                    remaining_time = max(0, time_limit - (time.time() - start_time))
                    time_text = game.font.render(f"时间: {int(remaining_time)}秒", True, (255, 215, 0))
                    time_rect = time_text.get_rect(topright=(game.display_width - 20, 20))
                    
                    # 添加文字背景
                    bg_rect = pygame.Rect(0, 0, time_rect.width + 10, time_rect.height + 5)
                    bg_rect.topleft = (time_rect.left - 5, time_rect.top - 2)
                    pygame.draw.rect(game.screen, (0, 0, 0, 180), bg_rect)
                    pygame.draw.rect(game.screen, (255, 215, 0), bg_rect, 1)
                    
                    game.screen.blit(time_text, time_rect)
                    pygame.display.flip()
                    
                    # 重置动作,避免连续移动
                    action = -1
                else:
                    game_state = "game_over"
                    # 保存游戏结束时间,用于固定显示时长
                    game.game_end_time = time.time()
        else:
            # 即使不在更新间隔,也要绘制界面(特别是剩余时间)
            if game_state == "running":
                # 只更新时间显示,不更新游戏状态
                remaining_time = max(0, time_limit - (time.time() - start_time))
                game.render(ai_connected, draw_opponent=False, show_ai=True)
                time_text = game.font.render(f"时间: {int(remaining_time)}秒", True, (255, 215, 0))
                time_rect = time_text.get_rect(topright=(game.display_width - 20, 20))
                bg_rect = pygame.Rect(0, 0, time_rect.width + 10, time_rect.height + 5)
                bg_rect.topleft = (time_rect.left - 5, time_rect.top - 2)
                pygame.draw.rect(game.screen, (0, 0, 0, 180), bg_rect)
                pygame.draw.rect(game.screen, (255, 215, 0), bg_rect, 1)
                game.screen.blit(time_text, time_rect)
                pygame.display.flip()
                
                time_text = game.font.render(f"时间: {int(remaining_time)}秒", True, (255, 215, 0))
                time_rect = time_text.get_rect(topright=(game.display_width - 20, 20))
                
                bg_rect = pygame.Rect(0, 0, time_rect.width + 10, time_rect.height + 5)
                bg_rect.topleft = (time_rect.left - 5, time_rect.top - 2)
                pygame.draw.rect(game.screen, (0, 0, 0, 180), bg_rect)
                pygame.draw.rect(game.screen, (255, 215, 0), bg_rect, 1)
                
                game.screen.blit(time_text, time_rect)
                pygame.display.flip()

        # 限制帧率
        clock.tick(60)


# ---------------------------
# 游戏主体配置
# ---------------------------

# 游戏配置全局变量
game_config = {
    "board_size": 40,
    "cell_size": 20,
    "snake_speed": 0.10,
    "enable_sound": True,
    "food_value": 1,
    "enable_border": True,
    "ai_difficulty": "medium"
}

# 图形界面模式选择 - 优化版
def main_gui():
    """图形界面模式选择 - 优化版"""
    pygame.init()
    # 增加窗口高度以容纳所有按钮
    screen = pygame.display.set_mode((600, 560))
    pygame.display.set_caption("贪吃蛇游戏 - 选择模式")

    # 加载图标
    try:
        icon = pygame.image.load("./icon.png")
        pygame.display.set_icon(icon)
    except pygame.error as e:
        print("图标加载失败:", e)

    # 尝试加载中文字体,提供多种备选字体
    try:
        font = pygame.font.SysFont(["SimHei", "WenQuanYi Micro Hei", "Heiti TC", "Arial"], 30)
        large_font = pygame.font.SysFont(["SimHei", "WenQuanYi Micro Hei", "Heiti TC", "Arial"], 48)
    except:
        # 如果无法加载中文字体,使用默认字体
        font = pygame.font.Font(None, 36)
        large_font = pygame.font.Font(None, 54)
    
    clock = pygame.time.Clock()
    running = True
    
    # 添加动画变量
    title_alpha = 0
    fade_in_speed = 5
    
    # 创建按钮类以简化代码和添加悬停效果
    class Button:
        def __init__(self, x, y, width, height, text, normal_color, hover_color, text_color, border_color):
            self.rect = pygame.Rect(x, y, width, height)
            self.text = text
            self.normal_color = normal_color
            self.hover_color = hover_color
            self.text_color = text_color
            self.border_color = border_color
            self.is_hovered = False
        
        def update(self, mouse_pos):
            self.is_hovered = self.rect.collidepoint(mouse_pos)
        
        def draw(self, surface, font):
            # 先绘制阴影(如果悬停)
            if self.is_hovered:
                shadow_offset = 3
                shadow_rect = self.rect.copy()
                shadow_rect.x += shadow_offset
                shadow_rect.y += shadow_offset
                # 使用半透明黑色,需要确保surface支持alpha
                shadow_surf = pygame.Surface((shadow_rect.width, shadow_rect.height), pygame.SRCALPHA)
                pygame.draw.rect(shadow_surf, (0, 0, 0, 100), (0, 0, shadow_rect.width, shadow_rect.height), border_radius=12)
                surface.blit(shadow_surf, (shadow_rect.x, shadow_rect.y))
            
            # 绘制按钮背景
            color = self.hover_color if self.is_hovered else self.normal_color
            pygame.draw.rect(surface, color, self.rect, border_radius=12)
            pygame.draw.rect(surface, self.border_color, self.rect, 3, border_radius=12)
            
            # 绘制按钮文本
            text_surf = font.render(self.text, True, self.text_color)
            text_rect = text_surf.get_rect(center=self.rect.center)
            surface.blit(text_surf, text_rect)
    
    # 初始化按钮
    btn_width, btn_height = 200, 50
    btn_spacing = 20
    bottom_margin = 50
    
    # 调整布局为两行
    row_spacing = 30
    
    # 计算起始位置使按钮居中
    first_row_y = 140
    second_row_y = first_row_y + btn_height + row_spacing
    third_row_y = second_row_y + btn_height + row_spacing
    center_x = 300
    
    fourth_row_y = third_row_y + btn_height + btn_spacing
    
    buttons = [
        # 第一行按钮
        Button(center_x - btn_width - btn_spacing//2, first_row_y, btn_width, btn_height, 
               "普通模式", (120, 220, 120), (140, 240, 140), (0, 0, 0), (80, 200, 80)),
        Button(center_x + btn_spacing//2, first_row_y, btn_width, btn_height, 
               "对抗模式", (120, 120, 220), (140, 140, 240), (0, 0, 0), (80, 80, 200)),
        # 第二行按钮
        Button(center_x - btn_width - btn_spacing//2, second_row_y, btn_width, btn_height, 
               "限时模式", (220, 180, 70), (240, 200, 90), (0, 0, 0), (180, 160, 50)),
        Button(center_x + btn_spacing//2, second_row_y, btn_width, btn_height, 
               "影子模式", (220, 70, 220), (240, 90, 240), (255, 255, 255), (180, 50, 180)),
        # 第三行按钮 - 设置
        Button(center_x - btn_width//2, third_row_y, btn_width, btn_height, 
               "游戏设置", (220, 220, 120), (240, 240, 140), (0, 0, 0), (180, 180, 100)),
        # 第四行按钮 - 帮助与教程
        Button(center_x - btn_width//2, fourth_row_y, btn_width, btn_height, 
               "帮助与教程", (220, 120, 220), (240, 140, 240), (0, 0, 0), (180, 100, 180)),
        # 底部退出按钮
        Button(center_x - btn_width//2, fourth_row_y + btn_height + btn_spacing, btn_width, btn_height, 
               "退出游戏", (220, 70, 70), (240, 90, 90), (255, 255, 255), (180, 50, 50))
    ]
    
    # 绘制模式选择界面
    def draw_mode_selection():
        # 绘制渐变背景
        for y in range(560):
            # 创建从深蓝色到黑色的垂直渐变
            r = int(0)
            g = int(0)
            b = int(50 - 50 * y / 560)
            pygame.draw.line(screen, (r, g, b), (0, y), (600, y))
        
        # 绘制标题(带淡入效果)
        title = large_font.render("贪吃蛇游戏", True, (255, 255, 255))
        
        # 创建一个带透明度的surface
        title_surf = pygame.Surface(title.get_size(), pygame.SRCALPHA)
        title_surf.fill((255, 255, 255, title_alpha))
        title_surf.blit(title, (0, 0), special_flags=pygame.BLEND_RGBA_MIN)
        
        title_rect = title.get_rect(center=(center_x, 80))
        screen.blit(title_surf, title_rect)
        
        # 绘制副标题
        subtitle = font.render("选择游戏模式", True, (200, 200, 200))
        subtitle_rect = subtitle.get_rect(center=(center_x, 120))
        screen.blit(subtitle, subtitle_rect)
        
        # 绘制所有按钮
        for button in buttons:
            button.draw(screen, font)
        
        # 添加版本信息
        version_text = font.render("v1.0.5 © 2025 Vincent Cassano", True, (100, 100, 100))
        screen.blit(version_text, (5, 530))
        
        pygame.display.flip()
    
    # 主循环
    while running:
        mouse_pos = pygame.mouse.get_pos()
        
        # 更新按钮状态
        for button in buttons:
            button.update(mouse_pos)
        
        # 处理淡入动画
        if title_alpha < 255:
            title_alpha = min(255, title_alpha + fade_in_speed)
        
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
                pygame.quit()
                sys.exit()
            elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
                # 检查按钮点击
                if buttons[0].rect.collidepoint(mouse_pos):
                    pygame.quit()
                    main_normal()
                    return
                elif buttons[1].rect.collidepoint(mouse_pos):
                    pygame.quit()
                    main_opponent()
                    return
                elif buttons[2].rect.collidepoint(mouse_pos):
                    pygame.quit()
                    main_timed()
                    return
                elif buttons[3].rect.collidepoint(mouse_pos):
                    pygame.quit()
                    main_three_snake()
                    return

                elif buttons[4].rect.collidepoint(mouse_pos):
                    pygame.quit()
                    main_settings()
                    return
                elif buttons[5].rect.collidepoint(mouse_pos):
                    pygame.quit()
                    main_help()
                    return
                elif buttons[6].rect.collidepoint(mouse_pos):
                    pygame.quit()
                    sys.exit()
            # 添加键盘支持
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_1:
                    pygame.quit()
                    main_normal()
                    return
                elif event.key == pygame.K_2:
                    pygame.quit()
                    main_opponent()
                    return
                elif event.key == pygame.K_3:
                    pygame.quit()
                    main_timed()
                    return
                elif event.key == pygame.K_4:
                    pygame.quit()
                    main_three_snake()
                    return

                elif event.key == pygame.K_5:
                    pygame.quit()
                    main_settings()
                    return
                elif event.key == pygame.K_6:
                    pygame.quit()
                    main_help()
                    return
                elif event.key == pygame.K_ESCAPE or event.key == pygame.K_q:
                    pygame.quit()
                    sys.exit()
        
        draw_mode_selection()
        clock.tick(60)  # 提高帧率使动画更流畅

# 游戏设置界面
def main_settings():
    """游戏设置界面 - 允许玩家自定义游戏参数"""
    pygame.init()
    screen = pygame.display.set_mode((700, 600))
    pygame.display.set_caption("贪吃蛇游戏 - 设置")

    # 加载图标
    try:
        icon = pygame.image.load("./icon.png")
        pygame.display.set_icon(icon)
    except pygame.error as e:
        print("图标加载失败:", e)
    
    # 尝试加载中文字体
    try:
        font = pygame.font.SysFont(["SimHei", "WenQuanYi Micro Hei", "Heiti TC", "Arial"], 24)
        large_font = pygame.font.SysFont(["SimHei", "WenQuanYi Micro Hei", "Heiti TC", "Arial"], 40)
        small_font = pygame.font.SysFont(["SimHei", "WenQuanYi Micro Hei", "Heiti TC", "Arial"], 20)
    except:
        font = pygame.font.Font(None, 30)
        large_font = pygame.font.Font(None, 48)
        small_font = pygame.font.Font(None, 24)
    
    # 创建游戏配置对象(使用默认值)
    config = {
        "board_size": 40,          # 棋盘大小
        "cell_size": 20,           # 格子大小
        "snake_speed": 0.10,       # 蛇移动速度
        "enable_sound": True,      # 声音开关
        "food_value": 1,           # 食物分值
        "enable_border": True,     # 边界碰撞
        #"ai_difficulty": "medium"  # AI难度
    }
    
    # 可配置选项列表
    options = [
        {"name": "棋盘大小", "type": "slider", "min": 10, "max": 40, "step": 5, "value": config["board_size"]},
        {"name": "游戏速度", "type": "slider", "min": 0.05, "max": 0.3, "step": 0.01, "value": config["snake_speed"]},
        {"name": "食物分值", "type": "slider", "min": 1, "max": 5, "step": 1, "value": config["food_value"]},
        {"name": "声音效果", "type": "toggle", "value": config["enable_sound"]},
        {"name": "边界碰撞", "type": "toggle", "value": config["enable_border"]},
        #{"name": "AI难度", "type": "dropdown", "options": ["简单", "中等", "困难"], "value": config["ai_difficulty"]}
    ]
    
    # 滑动条和开关类
    class Slider:
        def __init__(self, x, y, width, height, min_val, max_val, step, initial_val):
            self.rect = pygame.Rect(x, y, width, height)
            self.min_val = min_val
            self.max_val = max_val
            self.step = step
            self.value = initial_val
            self.is_dragging = False
            self.handle_width = 20
            self.handle_rect = pygame.Rect(
                x + (width - self.handle_width) * ((initial_val - min_val) / (max_val - min_val)),
                y - 3,
                self.handle_width,
                height + 6
            )
        
        def update(self, mouse_pos, mouse_down):
            if mouse_down:
                if self.handle_rect.collidepoint(mouse_pos):
                    self.is_dragging = True
                elif self.rect.collidepoint(mouse_pos):
                    # 点击滑动条上的位置
                    ratio = (mouse_pos[0] - self.rect.x) / self.rect.width
                    self.value = min(self.max_val, max(self.min_val, self.min_val + (self.max_val - self.min_val) * ratio))
                    # 四舍五入到最近的步长
                    self.value = round(self.value / self.step) * self.step
                    # 更新滑块位置
                    self.handle_rect.x = self.rect.x + (self.rect.width - self.handle_width) * ((self.value - self.min_val) / (self.max_val - self.min_val))
            else:
                self.is_dragging = False
            
            if self.is_dragging:
                # 拖动滑块
                new_x = max(self.rect.x, min(mouse_pos[0] - self.handle_width // 2, self.rect.right - self.handle_width))
                self.handle_rect.x = new_x
                ratio = (new_x - self.rect.x) / (self.rect.width - self.handle_width)
                self.value = min(self.max_val, max(self.min_val, self.min_val + (self.max_val - self.min_val) * ratio))
                # 四舍五入到最近的步长
                self.value = round(self.value / self.step) * self.step
            
            return self.value
        
        def draw(self, surface, font):
            # 绘制滑动条背景
            pygame.draw.rect(surface, (80, 80, 80), self.rect, border_radius=5)
            # 绘制滑动条填充部分
            fill_width = (self.handle_rect.centerx - self.rect.x)
            fill_rect = pygame.Rect(self.rect.x, self.rect.y, fill_width, self.rect.height)
            pygame.draw.rect(surface, (180, 180, 180), fill_rect, border_radius=5)
            # 绘制滑块
            pygame.draw.rect(surface, (220, 220, 220), self.handle_rect, border_radius=4)
            pygame.draw.rect(surface, (200, 200, 200), self.handle_rect, 2, border_radius=4)
            # 显示当前值
            value_text = small_font.render(str(round(self.value, 2)), True, (255, 255, 255))
            value_rect = value_text.get_rect(center=(self.rect.right + 40, self.rect.centery))
            surface.blit(value_text, value_rect)
    
    class ToggleSwitch:
        def __init__(self, x, y, width, height, initial_value):
            self.rect = pygame.Rect(x, y, width, height)
            self.value = initial_value
            self.is_on = initial_value
            self.circle_rect = pygame.Rect(
                x + 3 if not initial_value else x + width - height + 3,
                y + 3,
                height - 6,
                height - 6
            )
        
        def update(self, mouse_pos, mouse_down):
            if mouse_down and self.rect.collidepoint(mouse_pos):
                self.is_on = not self.is_on
                self.value = self.is_on
                # 更新圆形位置
                if self.is_on:
                    self.circle_rect.x = self.rect.x + self.rect.width - self.rect.height + 3
                else:
                    self.circle_rect.x = self.rect.x + 3
                return True
            return False
        
        def draw(self, surface, font=None):
            # 绘制开关背景
            bg_color = (80, 200, 80) if self.is_on else (100, 100, 100)
            pygame.draw.rect(surface, bg_color, self.rect, border_radius=15)
            # 绘制开关圆圈
            pygame.draw.circle(surface, (255, 255, 255), self.circle_rect.center, self.circle_rect.width // 2)
    
    class DropdownMenu:
        def __init__(self, x, y, width, height, options, initial_value):
            self.rect = pygame.Rect(x, y, width, height)
            self.options = options
            self.value = initial_value
            self.is_open = False
            self.option_rects = []
            for i, option in enumerate(options):
                self.option_rects.append(pygame.Rect(x, y + (i + 1) * height, width, height))
        
        def update(self, mouse_pos, mouse_down):
            if mouse_down:
                if self.rect.collidepoint(mouse_pos):
                    self.is_open = not self.is_open
                    return True
                elif self.is_open:
                    for i, rect in enumerate(self.option_rects):
                        if rect.collidepoint(mouse_pos):
                            self.value = self.options[i]
                            self.is_open = False
                            return True
                    # 点击外部关闭下拉菜单
                    self.is_open = False
            return False
        
        def draw(self, surface, font):
            # 绘制下拉菜单按钮
            pygame.draw.rect(surface, (80, 80, 80), self.rect, border_radius=5)
            pygame.draw.rect(surface, (120, 120, 120), self.rect, 1, border_radius=5)
            # 绘制当前选中的值
            text = font.render(self.value, True, (255, 255, 255))
            surface.blit(text, (self.rect.x + 10, self.rect.centery - text.get_height() // 2))
            # 绘制下拉箭头
            arrow_points = [(self.rect.right - 15, self.rect.centery - 5),
                            (self.rect.right - 5, self.rect.centery - 5),
                            (self.rect.right - 10, self.rect.centery + 5)]
            pygame.draw.polygon(surface, (255, 255, 255), arrow_points)
            
            # 绘制选项列表
            if self.is_open:
                for i, rect in enumerate(self.option_rects):
                    # 鼠标悬停检测 - 使用更亮的悬停颜色
                    hover_color = (150, 150, 180) if rect.collidepoint(pygame.mouse.get_pos()) else (80, 80, 80)
                    # 先绘制背景,确保完全覆盖
                    pygame.draw.rect(surface, hover_color, rect, border_radius=5)
                    # 绘制边框,确保没有漏边
                    pygame.draw.rect(surface, (120, 120, 120), rect, 1, border_radius=5)
                    option_text = font.render(self.options[i], True, (255, 255, 255))
                    surface.blit(option_text, (rect.x + 10, rect.centery - option_text.get_height() // 2))
    
    # 创建UI元素
    ui_elements = []
    y_pos = 120
    element_spacing = 60
    
    for i, option in enumerate(options):
        if option["type"] == "slider":
            ui_elements.append(Slider(200, y_pos, 300, 20, 
                                     option["min"], option["max"], option["step"], option["value"]))
        elif option["type"] == "toggle":
            ui_elements.append(ToggleSwitch(200, y_pos - 5, 80, 30, option["value"]))
        elif option["type"] == "dropdown":
            ui_elements.append(DropdownMenu(200, y_pos - 5, 150, 35, option["options"], option["value"]))
        y_pos += element_spacing
    
    # 创建按钮类
    class Button:
        def __init__(self, x, y, width, height, text, normal_color, hover_color, text_color, border_color):
            self.rect = pygame.Rect(x, y, width, height)
            self.text = text
            self.normal_color = normal_color
            self.hover_color = hover_color
            self.text_color = text_color
            self.border_color = border_color
            self.is_hovered = False
        
        def update(self, mouse_pos):
            self.is_hovered = self.rect.collidepoint(mouse_pos)
        
        def draw(self, surface, font):
            # 先绘制阴影(如果悬停)
            if self.is_hovered:
                shadow_offset = 2
                shadow_rect = self.rect.copy()
                shadow_rect.x += shadow_offset
                shadow_rect.y += shadow_offset
                # 使用半透明黑色
                shadow_surf = pygame.Surface((shadow_rect.width, shadow_rect.height), pygame.SRCALPHA)
                pygame.draw.rect(shadow_surf, (0, 0, 0, 80), (0, 0, shadow_rect.width, shadow_rect.height), border_radius=8)
                surface.blit(shadow_surf, (shadow_rect.x, shadow_rect.y))
            
            # 绘制按钮背景
            color = self.hover_color if self.is_hovered else self.normal_color
            pygame.draw.rect(surface, color, self.rect, border_radius=8)
            pygame.draw.rect(surface, self.border_color, self.rect, 2, border_radius=8)
            
            # 绘制按钮文本
            text_surf = font.render(self.text, True, self.text_color)
            text_rect = text_surf.get_rect(center=self.rect.center)
            surface.blit(text_surf, text_rect)
    
    # 创建保存和返回按钮
    save_button = Button(200, 520, 120, 40, "保存设置", (120, 200, 120), (140, 220, 140), (0, 0, 0), (80, 180, 80))
    back_button = Button(380, 520, 120, 40, "返回", (220, 120, 120), (240, 140, 140), (0, 0, 0), (180, 80, 80))
    
    # 保存配置到全局
    def save_config():
        # 更新配置字典
        for i, option in enumerate(options):
            if option["type"] == "slider":
                option["value"] = ui_elements[i].value
                if option["name"] == "棋盘大小":
                    config["board_size"] = int(ui_elements[i].value)
                elif option["name"] == "游戏速度":
                    config["snake_speed"] = ui_elements[i].value
                elif option["name"] == "食物分值":
                    config["food_value"] = int(ui_elements[i].value)
            elif option["type"] == "toggle":
                option["value"] = ui_elements[i].value
                if option["name"] == "声音效果":
                    config["enable_sound"] = ui_elements[i].value
                elif option["name"] == "边界碰撞":
                    config["enable_border"] = ui_elements[i].value
            # elif option["type"] == "dropdown":
            #     option["value"] = ui_elements[i].value
            #     if option["name"] == "AI难度":
            #         difficulty_map = {"简单": "easy", "中等": "medium", "困难": "hard", "easy": "easy", "medium": "medium", "hard": "hard"}
            #         config["ai_difficulty"] = difficulty_map[ui_elements[i].value]
        
        # 将配置保存为全局变量,让其他模式可以访问
        global game_config
        game_config = config
        
        # 显示保存成功提示
        show_success = True
        success_timer = 1.0  # 显示1秒
        return show_success, success_timer
    
    # 主循环
    running = True
    clock = pygame.time.Clock()
    show_success = False
    success_timer = 0
    
    while running:
        mouse_pos = pygame.mouse.get_pos()
        mouse_down = pygame.mouse.get_pressed()[0]
        
        # 更新按钮状态
        save_button.update(mouse_pos)
        back_button.update(mouse_pos)
        
        # 更新UI元素
        for element in ui_elements:
            element.update(mouse_pos, mouse_down)
        
        # 处理事件
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
                pygame.quit()
                sys.exit()
            elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
                # 检查按钮点击
                if save_button.rect.collidepoint(mouse_pos):
                    show_success, success_timer = save_config()
                elif back_button.rect.collidepoint(mouse_pos):
                    pygame.quit()
                    main_gui()
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    pygame.quit()
                    main_gui()
        
        # 更新成功提示计时器
        if show_success:
            success_timer -= 1/60  # 假设60FPS
            if success_timer <= 0:
                show_success = False
        
        # 绘制界面
        # 绘制渐变背景
        for y in range(600):
            r = int(20)
            g = int(20)
            b = int(40 - 30 * y / 600)
            pygame.draw.line(screen, (r, g, b), (0, y), (700, y))
        
        # 绘制标题
        title = large_font.render("游戏设置", True, (255, 255, 255))
        title_rect = title.get_rect(center=(350, 60))
        screen.blit(title, title_rect)
        
        # 绘制设置选项文本
        y_pos = 120
        for i, option in enumerate(options):
            option_text = font.render(option["name"], True, (220, 220, 220))
            screen.blit(option_text, (50, y_pos))
            y_pos += element_spacing
        
        # 绘制UI元素
        for element in ui_elements:
            if hasattr(element, 'draw'):
                element.draw(screen, font)
        
        # 绘制按钮
        save_button.draw(screen, font)
        back_button.draw(screen, font)
        
        # 绘制保存成功提示
        if show_success:
            # 创建半透明背景
            success_surf = pygame.Surface((300, 60), pygame.SRCALPHA)
            success_surf.fill((0, 120, 0, 180))
            pygame.draw.rect(success_surf, (0, 200, 0), (0, 0, 300, 60), 2, border_radius=10)
            screen.blit(success_surf, (200, 450))
            
            success_text = font.render("设置保存成功!", True, (255, 255, 255))
            text_rect = success_text.get_rect(center=(350, 480))
            screen.blit(success_text, text_rect)
        
        # 绘制说明文本
        help_text = small_font.render("提示: 部分设置需要重新开始游戏才能生效", True, (150, 150, 150))
        screen.blit(help_text, (180, 480))
        
        pygame.display.flip()
        clock.tick(60)

# 游戏帮助和教程界面
def main_help():
    """游戏帮助和教程界面"""
    pygame.init()
    screen = pygame.display.set_mode((800, 600))
    pygame.display.set_caption("贪吃蛇游戏 - 帮助与教程")

    # 加载图标
    try:
        icon = pygame.image.load("./icon.png")
        pygame.display.set_icon(icon)
    except pygame.error as e:
        print("图标加载失败:", e)
    
    # 尝试加载中文字体
    try:
        font = pygame.font.SysFont(["SimHei", "WenQuanYi Micro Hei", "Heiti TC", "Arial"], 24)
        large_font = pygame.font.SysFont(["SimHei", "WenQuanYi Micro Hei", "Heiti TC", "Arial"], 40)
        small_font = pygame.font.SysFont(["SimHei", "WenQuanYi Micro Hei", "Heiti TC", "Arial"], 20)
        tiny_font = pygame.font.SysFont(["SimHei", "WenQuanYi Micro Hei", "Heiti TC", "Arial"], 18)
    except:
        font = pygame.font.Font(None, 30)
        large_font = pygame.font.Font(None, 48)
        small_font = pygame.font.Font(None, 24)
        tiny_font = pygame.font.Font(None, 20)
    
    clock = pygame.time.Clock()
    
    # 创建按钮类
    class Button:
        def __init__(self, x, y, width, height, text, color, hover_color, text_color, border_color):
            self.rect = pygame.Rect(x, y, width, height)
            self.text = text
            self.color = color
            self.hover_color = hover_color
            self.text_color = text_color
            self.border_color = border_color
            self.is_hovered = False
        
        def draw(self, surface):
            # 先绘制阴影(如果悬停)
            if self.is_hovered:
                shadow_offset = 2
                shadow_rect = self.rect.copy()
                shadow_rect.x += shadow_offset
                shadow_rect.y += shadow_offset
                # 使用半透明黑色
                shadow_surf = pygame.Surface((shadow_rect.width, shadow_rect.height), pygame.SRCALPHA)
                pygame.draw.rect(shadow_surf, (0, 0, 0, 80), (0, 0, shadow_rect.width, shadow_rect.height), border_radius=10)
                surface.blit(shadow_surf, (shadow_rect.x, shadow_rect.y))
            
            # 绘制按钮背景
            color = self.hover_color if self.is_hovered else self.color
            pygame.draw.rect(surface, color, self.rect, border_radius=10)
            pygame.draw.rect(surface, self.border_color, self.rect, 2, border_radius=10)  # 边框
            
            # 绘制按钮文本
            text_surface = font.render(self.text, True, self.text_color)
            text_rect = text_surface.get_rect(center=self.rect.center)
            surface.blit(text_surface, text_rect)
        
        def update(self, mouse_pos):
            self.is_hovered = self.rect.collidepoint(mouse_pos)
    
    # 创建按钮
    btn_width, btn_height = 180, 50
    center_x = 400
    
    buttons = [
        Button(center_x - btn_width//2, 520, btn_width, btn_height, "返回主菜单", 
               (120, 120, 120), (140, 140, 140), (255, 255, 255), (80, 80, 80)),
    ]
    
    # 绘制渐变背景
    def draw_background():
        for y in range(600):
            # 创建从深蓝色到黑色的垂直渐变
            r = int(0)
            g = int(0)
            b = int(50 - 50 * y / 600)
            pygame.draw.line(screen, (r, g, b), (0, y), (800, y))
    
    # 绘制帮助内容
    def draw_help_content():
        # 标题
        title = large_font.render("游戏帮助与教程", True, (255, 215, 0))
        screen.blit(title, (400 - title.get_width()//2, 40))
        
        # 基本操作
        operation_title = font.render("基本操作:", True, (255, 255, 255))
        screen.blit(operation_title, (50, 100))
        
        operation_texts = [
            "方向键: 控制蛇的移动方向",
            "WASD: 也可以用来控制蛇的移动",
            "空格键: 暂停/继续游戏",
            "ESC键: 返回主菜单"
        ]
        
        for i, text in enumerate(operation_texts):
            text_surface = small_font.render(text, True, (200, 200, 255))
            screen.blit(text_surface, (70, 130 + i * 30))
        
        # 游戏规则
        rules_title = font.render("游戏规则:", True, (255, 255, 255))
        screen.blit(rules_title, (50, 300))
        
        rules_texts = [
            "1. 控制蛇吃掉食物,使蛇更长",
            "2. 不要撞到墙壁或自己身体",
            "3. 每吃掉一个食物,分数会增加",
            "4. 游戏难度会随着分数增加而提高"
        ]
        
        for i, text in enumerate(rules_texts):
            text_surface = small_font.render(text, True, (200, 200, 255))
            screen.blit(text_surface, (70, 330 + i * 30))
        
        # 游戏模式说明
        modes_title = font.render("游戏模式:", True, (255, 255, 255))
        screen.blit(modes_title, (400, 100))
        
        modes_texts = [
            "普通模式: 经典贪吃蛇玩法",
            "对抗模式: 与AI蛇进行对战",
            "限时模式: 在60秒内获得最高分数",
            "影子模式: 影子模仿玩家,影子死玩家也死",
            "提示: 使用游戏设置调整难度和参数"
        ]
        
        for i, text in enumerate(modes_texts):
            text_surface = tiny_font.render(text, True, (200, 200, 255))
            screen.blit(text_surface, (420, 130 + i * 30))
        
        # 快捷键提示
        shortcut_title = font.render("主菜单快捷键:", True, (255, 255, 255))
        screen.blit(shortcut_title, (400, 300))
        
        shortcut_texts = [
            "1-4: 选择游戏模式",
            "5: 打开游戏设置",
            "6: 打开帮助与教程",
            "ESC/q: 退出游戏"
        ]
        
        for i, text in enumerate(shortcut_texts):
            text_surface = tiny_font.render(text, True, (200, 200, 255))
            screen.blit(text_surface, (420, 330 + i * 25))
    
    # 主循环
    running = True
    while running:
        mouse_pos = pygame.mouse.get_pos()
        
        # 更新按钮状态
        for button in buttons:
            button.update(mouse_pos)
        
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
                pygame.quit()
                sys.exit()
            elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
                # 处理按钮点击
                if buttons[0].rect.collidepoint(mouse_pos):
                    pygame.quit()
                    main_gui()
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    pygame.quit()
                    main_gui()
        
        # 绘制界面
        draw_background()
        for button in buttons:
            button.draw(screen)
        draw_help_content()
        
        pygame.display.flip()
        clock.tick(60)


    pass  # 在实际使用时,会通过函数调用的方式进行保存和加载

# 游戏主入口
def main():
    """游戏主入口,提供模式选择"""
    # 默认直接进入图形界面模式以便验证功能
    main_gui()
    
    # 保留原始选择逻辑作为注释
    """
    print("===== 贪吃蛇游戏 =====\n")
    print("请选择游戏模式:")
    print("1. 普通模式")
    print("2. 对抗模式")
    print("3. 图形界面模式(显示模式选择界面)")
    
    choice = input("请输入选择 (1-3): ")
    
    if choice == "1":
        main_normal()
    elif choice == "2":
        main_opponent()
    elif choice == "3":
        main_gui()
    else:
        print("无效的选择,默认进入普通模式")
        main_normal()
    """


if __name__ == "__main__":
    main()