"""
迷宫游戏 006.迷宫 - 完整可运行版
修复所有问题，加大地图，优化鬼怪AI
"""

import pygame
import sys
import random
import time
import math
from collections import deque
import heapq

# 初始化pygame
pygame.init()

# 游戏常量
SCREEN_WIDTH, SCREEN_HEIGHT = 1280, 960
CELL_SIZE = 32
MAZE_WIDTH = 35
MAZE_HEIGHT = 25
FPS = 60

# 颜色定义
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 120, 255)
YELLOW = (255, 255, 0)
PURPLE = (180, 0, 255)
ORANGE = (255, 165, 0)
BROWN = (139, 69, 19)
CYAN = (0, 255, 255)
PINK = (255, 182, 193)
DARK_GREEN = (0, 100, 0)
DARK_RED = (139, 0, 0)

class Ghost:
    def __init__(self, x, y, color, speed=1):
        self.x = x
        self.y = y
        self.start_x = x
        self.start_y = y
        self.color = color
        self.speed = speed
        self.direction = random.choice(["up", "down", "left", "right"])
        self.move_counter = 0
        self.move_delay = 40
        self.chase_distance = 10
        self.chasing = False
        self.frightened = False
        self.frightened_timer = 0
        self.last_positions = []
        self.max_history = 5
        
    def move(self, maze, player_pos):
        """移动鬼怪"""
        if self.frightened:
            self.frightened_timer -= 1
            if self.frightened_timer <= 0:
                self.frightened = False
        
        self.move_counter += 1
        if self.move_counter < self.move_delay:
            return
        
        self.move_counter = 0
        
        px, py = player_pos
        
        distance = math.sqrt((self.x - px)**2 + (self.y - py)**2)
        
        if distance <= self.chase_distance:
            self.chasing = True
        else:
            self.chasing = False
        
        possible_directions = []
        directions = {
            "up": (0, -1),
            "down": (0, 1),
            "left": (-1, 0),
            "right": (1, 0)
        }
        
        for dir_name, (dx, dy) in directions.items():
            nx, ny = int(self.x + dx), int(self.y + dy)
            
            if (0 <= nx < maze.width and 0 <= ny < maze.height and 
                maze.grid[ny][nx] != 1):
                
                if maze.grid[ny][nx] == 3 and not self.frightened:
                    continue
                    
                new_pos = (nx, ny)
                if new_pos in self.last_positions:
                    continue
                    
                possible_directions.append((dir_name, dx, dy, nx, ny))
        
        if not possible_directions:
            for dir_name, (dx, dy) in directions.items():
                nx, ny = int(self.x + dx), int(self.y + dy)
                if (0 <= nx < maze.width and 0 <= ny < maze.height and 
                    maze.grid[ny][nx] != 1):
                    possible_directions.append((dir_name, dx, dy, nx, ny))
        
        if not possible_directions:
            return
        
        if self.chasing and not self.frightened:
            best_dir = None
            min_distance = float('inf')
            
            for dir_name, dx, dy, nx, ny in possible_directions:
                dist = math.sqrt((nx - px)**2 + (ny - py)**2)
                penalty = 0
                if maze.grid[ny][nx] == 3:
                    penalty += 5
                
                exit_count = 0
                for ddx, ddy in [(0, 1), (1, 0), (0, -1), (-1, 0)]:
                    nnx, nny = nx + ddx, ny + ddy
                    if (0 <= nnx < maze.width and 0 <= nny < maze.height and 
                        maze.grid[nny][nnx] != 1):
                        exit_count += 1
                
                if exit_count <= 1:
                    penalty += 3
                
                adjusted_dist = dist + penalty
                
                if adjusted_dist < min_distance:
                    min_distance = adjusted_dist
                    best_dir = dir_name
        elif self.frightened:
            best_dir = None
            max_distance = 0
            
            for dir_name, dx, dy, nx, ny in possible_directions:
                dist = math.sqrt((nx - px)**2 + (ny - py)**2)
                if dist > max_distance:
                    max_distance = dist
                    best_dir = dir_name
        else:
            if random.random() < 0.6 and any(d[0] == self.direction for d in possible_directions):
                best_dir = self.direction
            else:
                safe_directions = [d for d in possible_directions if maze.grid[d[4]][d[3]] != 3]
                if safe_directions:
                    best_dir = random.choice(safe_directions)[0]
                else:
                    best_dir = random.choice(possible_directions)[0]
        
        if best_dir:
            dx, dy = directions[best_dir]
            new_x = int(self.x + dx)
            new_y = int(self.y + dy)
            
            if (0 <= new_x < maze.width and 0 <= new_y < maze.height and 
                maze.grid[new_y][new_x] != 1):
                self.last_positions.append((self.x, self.y))
                if len(self.last_positions) > self.max_history:
                    self.last_positions.pop(0)
                
                self.x = new_x
                self.y = new_y
                self.direction = best_dir
    
    def draw(self, screen, cell_size, offset_x=0, offset_y=0):
        """绘制鬼怪"""
        if self.frightened:
            color = BLUE
        else:
            color = self.color
        
        x = self.x * cell_size + offset_x
        y = self.y * cell_size + offset_y
        
        pygame.draw.circle(screen, color, 
                          (x + cell_size//2, y + cell_size//2), 
                          cell_size//2 - 2)
        
        eye_radius = cell_size//6
        pygame.draw.circle(screen, WHITE, 
                          (x + cell_size//3, y + cell_size//3), 
                          eye_radius)
        pygame.draw.circle(screen, WHITE, 
                          (x + 2*cell_size//3, y + cell_size//3), 
                          eye_radius)
        
        pupil_radius = eye_radius//2
        if self.chasing and not self.frightened:
            pupil_color = RED
        else:
            pupil_color = BLACK
            
        pygame.draw.circle(screen, pupil_color, 
                          (x + cell_size//3, y + cell_size//3), 
                          pupil_radius)
        pygame.draw.circle(screen, pupil_color, 
                          (x + 2*cell_size//3, y + cell_size//3), 
                          pupil_radius)
    
    def frighten(self, duration=300):
        """使鬼怪恐惧"""
        self.frightened = True
        self.frightened_timer = duration
        self.chasing = False
        self.last_positions = []

class PowerUp:
    def __init__(self, x, y, type="speed"):
        self.x = x
        self.y = y
        self.type = type
        self.active = True
        self.blink_counter = 0
        
        if type == "speed":
            self.color = YELLOW
        elif type == "ghost_fright":
            self.color = BLUE
        elif type == "score":
            self.color = ORANGE
        elif type == "key":
            self.color = PURPLE
    
    def draw(self, screen, cell_size, offset_x=0, offset_y=0):
        """绘制道具"""
        if not self.active:
            return
        
        self.blink_counter += 1
        if self.blink_counter % 20 < 10:
            return
        
        x = self.x * cell_size + offset_x
        y = self.y * cell_size + offset_y
        
        if self.type == "speed":
            pygame.draw.polygon(screen, self.color, [
                (x + cell_size//2, y + 5),
                (x + cell_size - 5, y + cell_size//2),
                (x + cell_size//2, y + cell_size - 5),
                (x + 5, y + cell_size//2)
            ])
        elif self.type == "ghost_fright":
            pygame.draw.circle(screen, self.color, 
                             (x + cell_size//2, y + cell_size//2), 
                             cell_size//3)
        elif self.type == "score":
            self.draw_star(screen, x + cell_size//2, y + cell_size//2, 
                          cell_size//3, 5, self.color)
        elif self.type == "key":
            pygame.draw.rect(screen, self.color, 
                           (x + cell_size//3, y + cell_size//3, 
                            cell_size//3, cell_size//6))
            pygame.draw.circle(screen, self.color, 
                             (x + cell_size//2, y + cell_size//3 + cell_size//12), 
                             cell_size//6)
    
    def draw_star(self, screen, cx, cy, radius, n, color):
        """绘制星星"""
        points = []
        for i in range(2 * n):
            angle = math.pi / 2 - i * math.pi / n
            r = radius if i % 2 == 0 else radius / 2
            x = cx + r * math.cos(angle)
            y = cy - r * math.sin(angle)
            points.append((x, y))
        pygame.draw.polygon(screen, color, points)

class Maze:
    def __init__(self, width=MAZE_WIDTH, height=MAZE_HEIGHT):
        self.width = width
        self.height = height
        self.grid = [[1 for _ in range(width)] for _ in range(height)]
        self.start_pos = (1, 1)
        self.end_pos = (width - 2, height - 2)
        self.player_pos = list(self.start_pos)
        self.visited = set()
        self.path = []
        self.solution_path = []
        self.ghosts = []
        self.powerups = []
        self.doors = []
        self.keys_collected = 0
        self.keys_needed = 2
        self.score = 0
        self.game_mode = "play"
        self.show_solution = False
        self.auto_solve = False
        self.algorithm = "DFS"
        self.steps = 0
        self.start_time = 0
        self.elapsed_time = 0
        self.player_speed = 1
        self.speed_boost_time = 0
        self.generate_maze()
        
    def generate_maze(self):
        """生成迷宫"""
        for y in range(self.height):
            for x in range(self.width):
                self.grid[y][x] = 1
        
        x, y = 1, 1
        self.grid[y][x] = 0
        self.start_pos = (x, y)
        
        stack = [(x, y)]
        directions = [(0, 2), (2, 0), (0, -2), (-2, 0)]
        
        while stack:
            x, y = stack[-1]
            random.shuffle(directions)
            
            found = False
            for dx, dy in directions:
                nx, ny = x + dx, y + dy
                if 0 < nx < self.width - 1 and 0 < ny < self.height - 1 and self.grid[ny][nx] == 1:
                    self.grid[y + dy//2][x + dx//2] = 0
                    self.grid[ny][nx] = 0
                    stack.append((nx, ny))
                    found = True
                    break
            
            if not found:
                stack.pop()
        
        self.ensure_connectivity()
        
        self.end_pos = (self.width - 2, self.height - 2)
        self.grid[self.end_pos[1]][self.end_pos[0]] = 2
        
        self.player_pos = list(self.start_pos)
        
        self.add_doors(3)
        self.add_ghosts(6)
        self.add_powerups(10)
    
    def ensure_connectivity(self):
        """确保连通性"""
        visited = [[False for _ in range(self.width)] for _ in range(self.height)]
        queue = deque([self.start_pos])
        visited[self.start_pos[1]][self.start_pos[0]] = True
        reachable_cells = 1
        
        while queue:
            x, y = queue.popleft()
            
            for dx, dy in [(0, 1), (1, 0), (0, -1), (-1, 0)]:
                nx, ny = x + dx, y + dy
                if (0 <= nx < self.width and 0 <= ny < self.height and 
                    self.grid[ny][nx] == 0 and not visited[ny][nx]):
                    visited[ny][nx] = True
                    queue.append((nx, ny))
                    reachable_cells += 1
        
        if reachable_cells < (self.width * self.height) // 4:
            for _ in range(20):
                x = random.randint(1, self.width - 2)
                y = random.randint(1, self.height - 2)
                if self.grid[y][x] == 1:
                    for dx, dy in [(0, 1), (1, 0), (0, -1), (-1, 0)]:
                        nx, ny = x + dx, y + dy
                        if 0 <= nx < self.width and 0 <= ny < self.height and self.grid[ny][nx] == 0:
                            self.grid[y][x] = 0
                            break
    
    def add_doors(self, num_doors):
        """添加门"""
        self.doors = []
        door_positions = []
        
        potential_positions = [
            (self.width // 3, self.height // 2),
            (2 * self.width // 3, self.height // 2),
            (self.width // 2, self.height // 3),
            (self.width // 2, 2 * self.height // 3)
        ]
        
        for pos in potential_positions:
            if len(door_positions) >= num_doors:
                break
                
            x, y = pos
            if (self.grid[y][x] == 0 and 
                (x, y) != self.start_pos and 
                (x, y) != self.end_pos and
                not self.is_dead_end(x, y)):
                
                if self.has_alternative_path(x, y):
                    self.grid[y][x] = 3
                    self.doors.append((x, y))
                    door_positions.append((x, y))
        
        while len(door_positions) < num_doors:
            x = random.randint(3, self.width - 4)
            y = random.randint(3, self.height - 4)
            
            if (self.grid[y][x] == 0 and 
                (x, y) != self.start_pos and 
                (x, y) != self.end_pos and
                not self.is_dead_end(x, y) and
                not any(abs(x - dx) <= 2 and abs(y - dy) <= 2 for dx, dy in door_positions)):
                
                if self.has_alternative_path(x, y):
                    self.grid[y][x] = 3
                    self.doors.append((x, y))
                    door_positions.append((x, y))
    
    def is_dead_end(self, x, y):
        """检查死胡同"""
        exits = 0
        for dx, dy in [(0, 1), (1, 0), (0, -1), (-1, 0)]:
            nx, ny = x + dx, y + dy
            if 0 <= nx < self.width and 0 <= ny < self.height and self.grid[ny][nx] != 1:
                exits += 1
        return exits <= 1
    
    def has_alternative_path(self, x, y):
        """检查替代路径"""
        temp = self.grid[y][x]
        self.grid[y][x] = 1
        
        visited = [[False for _ in range(self.width)] for _ in range(self.height)]
        queue = deque([self.start_pos])
        visited[self.start_pos[1]][self.start_pos[0]] = True
        reachable = False
        
        while queue:
            cx, cy = queue.popleft()
            
            if (cx, cy) == self.end_pos:
                reachable = True
                break
            
            for dx, dy in [(0, 1), (1, 0), (0, -1), (-1, 0)]:
                nx, ny = cx + dx, cy + dy
                if (0 <= nx < self.width and 0 <= ny < self.height and 
                    self.grid[ny][nx] != 1 and not visited[ny][nx]):
                    visited[ny][nx] = True
                    queue.append((nx, ny))
        
        self.grid[y][x] = temp
        return reachable
    
    def add_ghosts(self, num_ghosts):
        """添加鬼怪"""
        self.ghosts = []
        ghost_colors = [RED, PINK, CYAN, ORANGE, GREEN, PURPLE]
        
        for i in range(num_ghosts):
            placed = False
            attempts = 0
            
            while not placed and attempts < 50:
                x = random.randint(3, self.width - 4)
                y = random.randint(3, self.height - 4)
                
                if (self.grid[y][x] == 0 and 
                    (x, y) != self.start_pos and 
                    (x, y) != self.end_pos and
                    self.grid[y][x] != 3 and
                    not any(abs(x - g.x) <= 3 and abs(y - g.y) <= 3 for g in self.ghosts)):
                    
                    color = ghost_colors[i % len(ghost_colors)]
                    self.ghosts.append(Ghost(x, y, color))
                    placed = True
                
                attempts += 1
    
    def add_powerups(self, num_powerups):
        """添加道具"""
        self.powerups = []
        
        for _ in range(num_powerups):
            placed = False
            attempts = 0
            
            while not placed and attempts < 30:
                x = random.randint(1, self.width - 2)
                y = random.randint(1, self.height - 2)
                
                if (self.grid[y][x] == 0 and 
                    (x, y) != self.start_pos and 
                    (x, y) != self.end_pos and
                    self.grid[y][x] != 3 and
                    not any(ghost.x == x and ghost.y == y for ghost in self.ghosts)):
                    
                    if not any(powerup.x == x and powerup.y == y for powerup in self.powerups):
                        powerup_type = random.choice(["speed", "ghost_fright", "score", "key"])
                        self.powerups.append(PowerUp(x, y, powerup_type))
                        placed = True
                
                attempts += 1
        
        has_key = any(p.type == "key" for p in self.powerups)
        if not has_key and self.powerups:
            self.powerups[0].type = "key"
            self.powerups[0].color = PURPLE
    
    def move_player(self, dx, dy):
        """移动玩家"""
        if self.game_mode != "play":
            return False
        
        speed = self.player_speed
        if time.time() - self.speed_boost_time < 5:
            speed = 2
        
        new_x = self.player_pos[0] + dx * speed
        new_y = self.player_pos[1] + dy * speed
        
        new_x_int = int(new_x)
        new_y_int = int(new_y)
        
        if (0 <= new_x_int < self.width and 0 <= new_y_int < self.height):
            if self.grid[new_y_int][new_x_int] == 3:
                if self.keys_collected >= self.keys_needed:
                    self.grid[new_y_int][new_x_int] = 0
                    self.score += 50
                else:
                    return False
            elif self.grid[new_y_int][new_x_int] == 1:
                return False
            
            self.player_pos[0] = new_x_int
            self.player_pos[1] = new_y_int
            self.steps += 1
            
            pos = tuple(self.player_pos)
            if pos not in self.visited:
                self.visited.add(pos)
                self.path.append(pos)
            
            self.check_powerups()
            
            if tuple(self.player_pos) == self.end_pos:
                return True
        
        return False
    
    def check_powerups(self):
        """检查道具"""
        px, py = self.player_pos
        for powerup in self.powerups:
            if powerup.active and int(powerup.x) == px and int(powerup.y) == py:
                powerup.active = False
                
                if powerup.type == "speed":
                    self.speed_boost_time = time.time()
                    self.score += 20
                elif powerup.type == "ghost_fright":
                    for ghost in self.ghosts:
                        ghost.frighten(300)
                    self.score += 30
                elif powerup.type == "score":
                    self.score += 100
                elif powerup.type == "key":
                    self.keys_collected += 1
                    self.score += 50
    
    def update_ghosts(self):
        """更新鬼怪"""
        for ghost in self.ghosts:
            ghost.move(self, tuple(self.player_pos))
            
            if (int(ghost.x) == self.player_pos[0] and 
                int(ghost.y) == self.player_pos[1]):
                if ghost.frightened:
                    self.ghosts.remove(ghost)
                    self.score += 200
                else:
                    return False
        
        return True
    
    def solve_maze(self):
        """求解迷宫"""
        if self.algorithm == "DFS":
            return self.solve_dfs()
        elif self.algorithm == "BFS":
            return self.solve_bfs()
        elif self.algorithm == "A*":
            return self.solve_astar()
        return False
    
    def solve_dfs(self):
        """深度优先搜索"""
        stack = [self.start_pos]
        visited = {self.start_pos: None}
        
        while stack:
            current = stack.pop()
            
            if current == self.end_pos:
                path = []
                while current is not None:
                    path.append(current)
                    current = visited[current]
                self.solution_path = list(reversed(path))
                return True
            
            x, y = current
            for dx, dy in [(0, 1), (1, 0), (0, -1), (-1, 0)]:
                nx, ny = x + dx, y + dy
                neighbor = (nx, ny)
                
                if (0 <= nx < self.width and 0 <= ny < self.height and 
                    self.grid[ny][nx] in [0, 2, 3] and neighbor not in visited):
                    visited[neighbor] = current
                    stack.append(neighbor)
        
        return False
    
    def solve_bfs(self):
        """广度优先搜索"""
        queue = deque([self.start_pos])
        visited = {self.start_pos: None}
        
        while queue:
            current = queue.popleft()
            
            if current == self.end_pos:
                path = []
                while current is not None:
                    path.append(current)
                    current = visited[current]
                self.solution_path = list(reversed(path))
                return True
            
            x, y = current
            for dx, dy in [(0, 1), (1, 0), (0, -1), (-1, 0)]:
                nx, ny = x + dx, y + dy
                neighbor = (nx, ny)
                
                if (0 <= nx < self.width and 0 <= ny < self.height and 
                    self.grid[ny][nx] in [0, 2, 3] and neighbor not in visited):
                    visited[neighbor] = current
                    queue.append(neighbor)
        
        return False
    
    def solve_astar(self):
        """A*算法"""
        def heuristic(a, b):
            return abs(a[0] - b[0]) + abs(a[1] - b[1])
        
        open_set = []
        heapq.heappush(open_set, (0, self.start_pos))
        
        came_from = {}
        g_score = {self.start_pos: 0}
        f_score = {self.start_pos: heuristic(self.start_pos, self.end_pos)}
        
        while open_set:
            current_f, current = heapq.heappop(open_set)
            
            if current == self.end_pos:
                path = []
                while current in came_from:
                    path.append(current)
                    current = came_from[current]
                path.append(self.start_pos)
                self.solution_path = list(reversed(path))
                return True
            
            x, y = current
            for dx, dy in [(0, 1), (1, 0), (0, -1), (-1, 0)]:
                nx, ny = x + dx, y + dy
                neighbor = (nx, ny)
                
                if (0 <= nx < self.width and 0 <= ny < self.height and 
                    self.grid[ny][nx] in [0, 2, 3]):
                    
                    tentative_g = g_score[current] + 1
                    
                    if neighbor not in g_score or tentative_g < g_score[neighbor]:
                        came_from[neighbor] = current
                        g_score[neighbor] = tentative_g
                        f_score[neighbor] = tentative_g + heuristic(neighbor, self.end_pos)
                        heapq.heappush(open_set, (f_score[neighbor], neighbor))
        
        return False
    
    def reset(self):
        """重置游戏"""
        self.player_pos = list(self.start_pos)
        self.visited = {tuple(self.start_pos)}
        self.path = [tuple(self.start_pos)]
        self.solution_path = []
        self.steps = 0
        self.score = 0
        self.keys_collected = 0
        self.speed_boost_time = 0
        self.start_time = time.time()
        self.elapsed_time = 0
        
        for ghost in self.ghosts:
            ghost.x, ghost.y = ghost.start_x, ghost.start_y
            ghost.frightened = False
        
        for powerup in self.powerups:
            powerup.active = True
    
    def toggle_mode(self):
        """切换模式"""
        modes = ["play", "solve", "edit"]
        current_index = modes.index(self.game_mode)
        self.game_mode = modes[(current_index + 1) % len(modes)]
    
    def toggle_algorithm(self):
        """切换算法"""
        algorithms = ["DFS", "BFS", "A*"]
        current_index = algorithms.index(self.algorithm)
        self.algorithm = algorithms[(current_index + 1) % len(algorithms)]
        self.solution_path = []
    
    def edit_cell(self, pos):
        """编辑单元格"""
        if self.game_mode != "edit":
            return
        
        x, y = pos
        if 0 <= x < self.width and 0 <= y < self.height:
            if (x, y) != self.start_pos and (x, y) != self.end_pos:
                self.grid[y][x] = 1 - self.grid[y][x]
    
    def generate_random_maze(self):
        """生成随机迷宫"""
        for y in range(self.height):
            for x in range(self.width):
                if x == 0 or y == 0 or x == self.width - 1 or y == self.height - 1:
                    self.grid[y][x] = 1
                else:
                    self.grid[y][x] = 1 if random.random() < 0.3 else 0
        
        self.grid[self.start_pos[1]][self.start_pos[0]] = 0
        self.grid[self.end_pos[1]][self.end_pos[0]] = 2
        self.reset()
    
    def draw(self, screen, offset_x=0, offset_y=0, show_minimap=True):
        """绘制迷宫"""
        screen.fill((20, 20, 40))
        
        visible_cells_x = min(self.width, SCREEN_WIDTH // CELL_SIZE)
        visible_cells_y = min(self.height, (SCREEN_HEIGHT - 120) // CELL_SIZE)
        
        start_x = max(0, min(self.player_pos[0] - visible_cells_x // 2, self.width - visible_cells_x))
        start_y = max(0, min(self.player_pos[1] - visible_cells_y // 2, self.height - visible_cells_y))
        
        end_x = min(start_x + visible_cells_x, self.width)
        end_y = min(start_y + visible_cells_y, self.height)
        
        for y in range(start_y, end_y):
            for x in range(start_x, end_x):
                cell_x = (x - start_x) * CELL_SIZE + offset_x
                cell_y = (y - start_y) * CELL_SIZE + offset_y
                
                if cell_x < 0 or cell_x >= SCREEN_WIDTH or cell_y < 0 or cell_y >= SCREEN_HEIGHT - 120:
                    continue
                
                if self.grid[y][x] == 1:
                    pygame.draw.rect(screen, (60, 60, 100), 
                                   (cell_x, cell_y, CELL_SIZE, CELL_SIZE))
                    pygame.draw.rect(screen, (40, 40, 80), 
                                   (cell_x + 2, cell_y + 2, CELL_SIZE - 4, CELL_SIZE - 4))
                elif self.grid[y][x] == 0:
                    pygame.draw.rect(screen, (30, 30, 50), 
                                   (cell_x, cell_y, CELL_SIZE, CELL_SIZE))
                elif self.grid[y][x] == 2:
                    pygame.draw.rect(screen, (30, 30, 50), 
                                   (cell_x, cell_y, CELL_SIZE, CELL_SIZE))
                    pygame.draw.rect(screen, DARK_RED, 
                                   (cell_x + 5, cell_y + 5, CELL_SIZE - 10, CELL_SIZE - 10))
                    pygame.draw.rect(screen, RED, 
                                   (cell_x + 8, cell_y + 8, CELL_SIZE - 16, CELL_SIZE - 16))
                    font = pygame.font.Font(None, 20)
                    exit_text = font.render("EXIT", True, WHITE)
                    text_rect = exit_text.get_rect(center=(cell_x + CELL_SIZE//2, cell_y + CELL_SIZE//2))
                    screen.blit(exit_text, text_rect)
                elif self.grid[y][x] == 3:
                    pygame.draw.rect(screen, (30, 30, 50), 
                                   (cell_x, cell_y, CELL_SIZE, CELL_SIZE))
                    pygame.draw.rect(screen, BROWN, 
                                   (cell_x + 5, cell_y + 5, CELL_SIZE - 10, CELL_SIZE - 10))
                    pygame.draw.rect(screen, (100, 50, 0), 
                                   (cell_x + 8, cell_y + 8, CELL_SIZE - 16, CELL_SIZE - 16))
        
        for (x, y) in self.visited:
            if start_x <= x < end_x and start_y <= y < end_y:
                cell_x = (x - start_x) * CELL_SIZE + offset_x
                cell_y = (y - start_y) * CELL_SIZE + offset_y
                if 0 <= cell_x < SCREEN_WIDTH and 0 <= cell_y < SCREEN_HEIGHT - 120:
                    pygame.draw.rect(screen, (50, 100, 50, 100), 
                                   (cell_x, cell_y, CELL_SIZE, CELL_SIZE))
        
        if self.show_solution and self.solution_path:
            for i, (x, y) in enumerate(self.solution_path):
                if start_x <= x < end_x and start_y <= y < end_y:
                    cell_x = (x - start_x) * CELL_SIZE + offset_x
                    cell_y = (y - start_y) * CELL_SIZE + offset_y
                    if 0 <= cell_x < SCREEN_WIDTH and 0 <= cell_y < SCREEN_HEIGHT - 120:
                        color_ratio = i / len(self.solution_path)
                        r = int(255 * color_ratio)
                        g = int(100 + 155 * (1 - color_ratio))
                        b = int(255 * (1 - color_ratio))
                        pygame.draw.rect(screen, (r, g, b, 150), 
                                       (cell_x, cell_y, CELL_SIZE, CELL_SIZE))
        
        for powerup in self.powerups:
            if powerup.active and start_x <= powerup.x < end_x and start_y <= powerup.y < end_y:
                cell_x = (powerup.x - start_x) * CELL_SIZE + offset_x
                cell_y = (powerup.y - start_y) * CELL_SIZE + offset_y
                if 0 <= cell_x < SCREEN_WIDTH and 0 <= cell_y < SCREEN_HEIGHT - 120:
                    powerup.draw(screen, CELL_SIZE, 0, 0)
        
        for ghost in self.ghosts:
            if start_x <= ghost.x < end_x and start_y <= ghost.y < end_y:
                cell_x = (ghost.x - start_x) * CELL_SIZE + offset_x
                cell_y = (ghost.y - start_y) * CELL_SIZE + offset_y
                if 0 <= cell_x < SCREEN_WIDTH and 0 <= cell_y < SCREEN_HEIGHT - 120:
                    ghost.draw(screen, CELL_SIZE, 0, 0)
        
        sx, sy = self.start_pos
        if start_x <= sx < end_x and start_y <= sy < end_y:
            start_cell_x = (sx - start_x) * CELL_SIZE + offset_x
            start_cell_y = (sy - start_y) * CELL_SIZE + offset_y
            if 0 <= start_cell_x < SCREEN_WIDTH and 0 <= start_cell_y < SCREEN_HEIGHT - 120:
                pygame.draw.rect(screen, (30, 30, 50), 
                                (start_cell_x, start_cell_y, CELL_SIZE, CELL_SIZE))
                pygame.draw.rect(screen, DARK_GREEN, 
                                (start_cell_x + 5, start_cell_y + 5, CELL_SIZE - 10, CELL_SIZE - 10))
                pygame.draw.rect(screen, GREEN, 
                                (start_cell_x + 8, start_cell_y + 8, CELL_SIZE - 16, CELL_SIZE - 16))
                font = pygame.font.Font(None, 20)
                start_text = font.render("START", True, WHITE)
                text_rect = start_text.get_rect(center=(start_cell_x + CELL_SIZE//2, start_cell_y + CELL_SIZE//2))
                screen.blit(start_text, text_rect)
        
        px, py = self.player_pos
        if start_x <= px < end_x and start_y <= py < end_y:
            player_cell_x = (px - start_x) * CELL_SIZE + offset_x
            player_cell_y = (py - start_y) * CELL_SIZE + offset_y
            
            if 0 <= player_cell_x < SCREEN_WIDTH and 0 <= player_cell_y < SCREEN_HEIGHT - 120:
                if time.time() - self.speed_boost_time < 5:
                    player_color = CYAN
                else:
                    player_color = YELLOW
                    
                pygame.draw.circle(screen, player_color, 
                                  (player_cell_x + CELL_SIZE//2, player_cell_y + CELL_SIZE//2), 
                                  CELL_SIZE//2 - 4)
                
                if len(self.path) > 1:
                    prev_x, prev_y = self.path[-2]
                    dx = px - prev_x
                    dy = py - prev_y
                    
                    eye_offset = CELL_SIZE//4
                    if dx > 0:
                        eye1 = (player_cell_x + CELL_SIZE//2 + eye_offset, player_cell_y + CELL_SIZE//3)
                        eye2 = (player_cell_x + CELL_SIZE//2 + eye_offset, player_cell_y + 2*CELL_SIZE//3)
                    elif dx < 0:
                        eye1 = (player_cell_x + CELL_SIZE//2 - eye_offset, player_cell_y + CELL_SIZE//3)
                        eye2 = (player_cell_x + CELL_SIZE//2 - eye_offset, player_cell_y + 2*CELL_SIZE//3)
                    elif dy > 0:
                        eye1 = (player_cell_x + CELL_SIZE//3, player_cell_y + CELL_SIZE//2 + eye_offset)
                        eye2 = (player_cell_x + 2*CELL_SIZE//3, player_cell_y + CELL_SIZE//2 + eye_offset)
                    else:
                        eye1 = (player_cell_x + CELL_SIZE//3, player_cell_y + CELL_SIZE//2 - eye_offset)
                        eye2 = (player_cell_x + 2*CELL_SIZE//3, player_cell_y + CELL_SIZE//2 - eye_offset)
                    
                    pygame.draw.circle(screen, BLACK, eye1, CELL_SIZE//6)
                    pygame.draw.circle(screen, BLACK, eye2, CELL_SIZE//6)
        
        if show_minimap:
            self.draw_minimap(screen)
        
        self.draw_info_panel(screen)
        
        border_rect = pygame.Rect(offset_x, offset_y, 
                                 visible_cells_x * CELL_SIZE, 
                                 visible_cells_y * CELL_SIZE)
        pygame.draw.rect(screen, CYAN, border_rect, 2)
        
        font = pygame.font.Font(None, 20)
        coord_text = font.render(f"位置: ({px}, {py})", True, WHITE)
        screen.blit(coord_text, (10, 10))
    
    def draw_minimap(self, screen):
        """绘制小地图"""
        minimap_size = 250
        minimap_cell = minimap_size // max(self.width, self.height)
        minimap_x = SCREEN_WIDTH - minimap_size - 20
        minimap_y = 20
        
        pygame.draw.rect(screen, (0, 0, 0, 180), 
                        (minimap_x, minimap_y, minimap_size, minimap_size))
        pygame.draw.rect(screen, WHITE, 
                        (minimap_x, minimap_y, minimap_size, minimap_size), 2)
        
        for y in range(self.height):
            for x in range(self.width):
                cell_x = minimap_x + x * minimap_cell
                cell_y = minimap_y + y * minimap_cell
                
                if self.grid[y][x] == 1:
                    pygame.draw.rect(screen, (100, 100, 150), 
                                   (cell_x, cell_y, minimap_cell, minimap_cell))
                elif self.grid[y][x] == 0:
                    pygame.draw.rect(screen, (50, 50, 80), 
                                   (cell_x, cell_y, minimap_cell, minimap_cell))
                elif self.grid[y][x] == 2:
                    pygame.draw.rect(screen, RED, 
                                   (cell_x, cell_y, minimap_cell, minimap_cell))
                elif self.grid[y][x] == 3:
                    pygame.draw.rect(screen, BROWN, 
                                   (cell_x, cell_y, minimap_cell, minimap_cell))
        
        for (x, y) in self.visited:
            cell_x = minimap_x + x * minimap_cell
            cell_y = minimap_y + y * minimap_cell
            pygame.draw.rect(screen, GREEN, 
                           (cell_x, cell_y, minimap_cell, minimap_cell))
        
        px, py = self.player_pos
        player_x = minimap_x + px * minimap_cell
        player_y = minimap_y + py * minimap_cell
        pygame.draw.rect(screen, YELLOW, 
                        (player_x, player_y, minimap_cell, minimap_cell))
        
        for ghost in self.ghosts:
            gx, gy = int(ghost.x), int(ghost.y)
            ghost_x = minimap_x + gx * minimap_cell
            ghost_y = minimap_y + gy * minimap_cell
            if ghost.frightened:
                ghost_color = BLUE
            else:
                ghost_color = ghost.color
            pygame.draw.rect(screen, ghost_color, 
                           (ghost_x, ghost_y, minimap_cell, minimap_cell))
        
        font = pygame.font.Font(None, 20)
        title = font.render("小地图", True, WHITE)
        screen.blit(title, (minimap_x + minimap_size//2 - title.get_width()//2, 
                          minimap_y - 25))
    
    def draw_info_panel(self, screen):
        """绘制信息面板"""
        panel_height = 120
        panel_rect = pygame.Rect(0, SCREEN_HEIGHT - panel_height, SCREEN_WIDTH, panel_height)
        pygame.draw.rect(screen, (30, 30, 50, 200), panel_rect)
        pygame.draw.line(screen, CYAN, (0, SCREEN_HEIGHT - panel_height), 
                        (SCREEN_WIDTH, SCREEN_HEIGHT - panel_height), 2)
        
        font = pygame.font.Font(None, 24)
        font_small = pygame.font.Font(None, 20)
        
        left_x = 20
        y_start = SCREEN_HEIGHT - panel_height + 20
        
        mode_text = font.render(f"模式: {self.game_mode.upper()}", True, CYAN)
        screen.blit(mode_text, (left_x, y_start))
        
        algo_text = font.render(f"算法: {self.algorithm}", True, WHITE)
        screen.blit(algo_text, (left_x, y_start + 30))
        
        steps_text = font.render(f"步数: {self.steps}", True, WHITE)
        screen.blit(steps_text, (left_x, y_start + 60))
        
        mid_x = SCREEN_WIDTH // 3
        
        time_text = font.render(f"时间: {self.elapsed_time:.1f}s", True, WHITE)
        screen.blit(time_text, (mid_x, y_start))
        
        score_text = font.render(f"分数: {self.score}", True, ORANGE)
        screen.blit(score_text, (mid_x, y_start + 30))
        
        keys_text = font.render(f"钥匙: {self.keys_collected}/{self.keys_needed}", True, PURPLE)
        screen.blit(keys_text, (mid_x, y_start + 60))
        
        right_x = 2 * SCREEN_WIDTH // 3
        
        speed_boost = max(0, 5 - (time.time() - self.speed_boost_time))
        if speed_boost > 0:
            speed_text = font.render(f"加速: {speed_boost:.1f}s", True, YELLOW)
            screen.blit(speed_text, (right_x, y_start))
        
        frightened_ghosts = sum(1 for g in self.ghosts if g.frightened)
        if frightened_ghosts > 0:
            ghost_text = font.render(f"恐惧鬼怪: {frightened_ghosts}", True, BLUE)
            screen.blit(ghost_text, (right_x, y_start + 30))
        
        ghost_count = font.render(f"鬼怪: {len(self.ghosts)}", True, RED)
        screen.blit(ghost_count, (right_x, y_start + 60))
        
        controls_y = SCREEN_HEIGHT - 40
        controls = [
            "ESC:退出  R:重置  N:新迷宫  M:模式  S:解法  A:自动  C:算法  G:随机  P:道具"
        ]
        
        for i, control in enumerate(controls):
            control_text = font_small.render(control, True, GREEN)
            screen.blit(control_text, (SCREEN_WIDTH//2 - control_text.get_width()//2, 
                                     controls_y + i*20))

class Game:
    def __init__(self):
        self.screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
        pygame.display.set_caption("006.迷宫游戏 - 鬼怪大冒险")
        self.clock = pygame.time.Clock()
        self.maze = Maze(MAZE_WIDTH, MAZE_HEIGHT)
        self.running = True
        self.game_state = "playing"
        self.show_menu = False
        self.camera_x = 0
        self.camera_y = 0
        self.maze.reset()
    
    def handle_events(self):
        """处理事件"""
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                self.running = False
            
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    self.running = False
                
                elif event.key == pygame.K_r:
                    self.maze.reset()
                    self.game_state = "playing"
                    print("游戏已重置")
                
                elif event.key == pygame.K_n:
                    self.maze.generate_maze()
                    self.maze.reset()
                    self.game_state = "playing"
                    print("生成新迷宫")
                
                elif event.key == pygame.K_m:
                    self.maze.toggle_mode()
                    print(f"切换到模式: {self.maze.game_mode}")
                
                elif event.key == pygame.K_s:
                    self.maze.show_solution = not self.maze.show_solution
                    if self.maze.show_solution and not self.maze.solution_path:
                        if self.maze.solve_maze():
                            print("找到解法路径")
                        else:
                            print("无解")
                    print(f"显示解法: {self.maze.show_solution}")
                
                elif event.key == pygame.K_a:
                    self.maze.auto_solve = not self.maze.auto_solve
                    if self.maze.auto_solve:
                        if self.maze.solve_maze():
                            print("开始自动求解")
                        else:
                            self.maze.auto_solve = False
                            print("无解")
                    print(f"自动求解: {self.maze.auto_solve}")
                
                elif event.key == pygame.K_c:
                    self.maze.toggle_algorithm()
                    print(f"切换到算法: {self.maze.algorithm}")
                
                elif event.key == pygame.K_g:
                    self.maze.generate_random_maze()
                    self.game_state = "playing"
                    print("生成随机迷宫")
                
                elif event.key == pygame.K_p:
                    for _ in range(3):
                        x = random.randint(1, self.maze.width - 2)
                        y = random.randint(1, self.maze.height - 2)
                        if self.maze.grid[y][x] == 0:
                            powerup_type = random.choice(["speed", "ghost_fright", "score", "key"])
                            self.maze.powerups.append(PowerUp(x, y, powerup_type))
                    print("添加随机道具")
                
                elif event.key == pygame.K_SPACE:
                    if self.game_state == "won" or self.game_state == "lost":
                        self.maze.generate_maze()
                        self.maze.reset()
                        self.game_state = "playing"
                        print("开始新游戏")
            
            elif event.type == pygame.MOUSEBUTTONDOWN:
                if self.maze.game_mode == "edit":
                    x, y = pygame.mouse.get_pos()
                    cell_x = (x - self.camera_x) // CELL_SIZE
                    cell_y = (y - self.camera_y) // CELL_SIZE
                    self.maze.edit_cell((cell_x, cell_y))
        
        if self.maze.game_mode == "play" and not self.maze.auto_solve and self.game_state == "playing":
            keys = pygame.key.get_pressed()
            moved = False
            
            if keys[pygame.K_UP] or keys[pygame.K_w]:
                moved = self.maze.move_player(0, -1)
            if keys[pygame.K_DOWN] or keys[pygame.K_s]:
                moved = self.maze.move_player(0, 1) or moved
            if keys[pygame.K_LEFT] or keys[pygame.K_a]:
                moved = self.maze.move_player(-1, 0) or moved
            if keys[pygame.K_RIGHT] or keys[pygame.K_d]:
                moved = self.maze.move_player(1, 0) or moved
            
            if moved and tuple(self.maze.player_pos) == self.maze.end_pos:
                self.game_state = "won"
                self.maze.score += 1000
                print("恭喜通关!")
        
        if self.maze.auto_solve and self.game_state == "playing":
            if not self.maze.solution_path:
                if self.maze.solve_maze():
                    print("开始自动求解路径")
                else:
                    self.maze.auto_solve = False
                    print("无解，停止自动求解")
            elif self.maze.player_pos != list(self.maze.end_pos):
                if self.maze.path and tuple(self.maze.player_pos) == self.maze.path[-1]:
                    if self.maze.solution_path:
                        next_pos = self.maze.solution_path.pop(0)
                        self.maze.player_pos = list(next_pos)
                        self.maze.steps += 1
                        self.maze.visited.add(next_pos)
                        self.maze.path.append(next_pos)
            else:
                self.game_state = "won"
                self.maze.auto_solve = False
                self.maze.score += 1000
                print("自动求解完成!")
    
    def update_camera(self):
        """更新相机"""
        maze_width_px = self.maze.width * CELL_SIZE
        maze_height_px = self.maze.height * CELL_SIZE
        
        visible_cells_x = min(self.maze.width, SCREEN_WIDTH // CELL_SIZE)
        visible_cells_y = min(self.maze.height, (SCREEN_HEIGHT - 120) // CELL_SIZE)
        
        start_x = max(0, min(self.maze.player_pos[0] - visible_cells_x // 2, self.maze.width - visible_cells_x))
        start_y = max(0, min(self.maze.player_pos[1] - visible_cells_y // 2, self.maze.height - visible_cells_y))
        
        maze_display_width = visible_cells_x * CELL_SIZE
        maze_display_height = visible_cells_y * CELL_SIZE
        
        self.camera_x = (SCREEN_WIDTH - maze_display_width) // 2
        self.camera_y = (SCREEN_HEIGHT - 120 - maze_display_height) // 2
    
    def update(self):
        """更新游戏状态"""
        if self.game_state == "playing":
            self.maze.elapsed_time = time.time() - self.maze.start_time
            
            if not self.maze.update_ghosts():
                self.game_state = "lost"
                print("被鬼怪抓住了!")
            
            self.update_camera()
    
    def draw(self):
        """绘制游戏"""
        self.maze.draw(self.screen, self.camera_x, self.camera_y)
        
        if self.game_state == "won":
            self.draw_end_screen("恭喜通关!", GREEN)
        elif self.game_state == "lost":
            self.draw_end_screen("被鬼怪抓住了!", RED)
        
        pygame.display.flip()
    
    def draw_end_screen(self, message, color):
        """绘制结束屏幕"""
        overlay = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT), pygame.SRCALPHA)
        overlay.fill((0, 0, 0, 180))
        self.screen.blit(overlay, (0, 0))
        
        font_large = pygame.font.Font(None, 72)
        font_medium = pygame.font.Font(None, 36)
        
        msg_text = font_large.render(message, True, color)
        self.screen.blit(msg_text, (SCREEN_WIDTH//2 - msg_text.get_width()//2, SCREEN_HEIGHT//3))
        
        stats = [
            f"最终分数: {self.maze.score}",
            f"所用步数: {self.maze.steps}",
            f"所用时间: {self.maze.elapsed_time:.2f}秒",
            f"探索区域: {len(self.maze.visited)}/{self.maze.width * self.maze.height}",
            f"收集钥匙: {self.maze.keys_collected}/{self.maze.keys_needed}"
        ]
        
        for i, stat in enumerate(stats):
            stat_text = font_medium.render(stat, True, WHITE)
            self.screen.blit(stat_text, (SCREEN_WIDTH//2 - stat_text.get_width()//2, 
                                       SCREEN_HEIGHT//2 + i*40))
        
        hint_text = font_medium.render("按空格键开始新游戏，按ESC退出", True, CYAN)
        self.screen.blit(hint_text, (SCREEN_WIDTH//2 - hint_text.get_width()//2, SCREEN_HEIGHT*3//4))
    
    def run(self):
        """运行游戏"""
        self.maze.start_time = time.time()
        
        while self.running:
            self.handle_events()
            self.update()
            self.draw()
            self.clock.tick(FPS)
        
        pygame.quit()
        sys.exit()

def main():
    """主函数"""
    print("=" * 60)
    print("迷宫游戏 006.迷宫 - 完整修复版")
    print("=" * 60)
    print("\n游戏特性:")
    print("  - 35x25 超大迷宫")
    print("  - 6个智能鬼怪")
    print("  - 10个随机道具")
    print("  - 3个门，需要2把钥匙")
    print("  - 视野跟随系统")
    print("  - 实时小地图")
    print("\n游戏控制:")
    print("  - 方向键/WASD: 移动玩家")
    print("  - R: 重置游戏")
    print("  - N: 生成新迷宫")
    print("  - M: 切换模式 (游玩/求解/编辑)")
    print("  - S: 显示/隐藏解法")
    print("  - A: 自动求解")
    print("  - C: 切换算法 (DFS/BFS/A*)")
    print("  - G: 生成随机迷宫")
    print("  - P: 添加随机道具")
    print("  - ESC: 退出游戏")
    print("\n游戏提示:")
    print("  - 蓝色道具使鬼怪恐惧")
    print("  - 黄色道具获得加速")
    print("  - 紫色钥匙可以开门")
    print("  - 鬼怪会避免堵门")
    print("\n" + "=" * 60)
    print("游戏开始! 祝你好运!")
    print("提示: 游戏窗口可能需要几秒钟加载...")
    
    game = Game()
    game.run()

if __name__ == "__main__":
    main()