import tkinter as tk
import random
import time

# 迷宫配置
ROWS = 21   # 行数（最好为奇数）
COLS = 21   # 列数（最好为奇数）
CELL_SIZE = 25  # 每个格子像素大小
WALL_COLOR = "black"
PATH_COLOR = "white"
PLAYER_COLOR = "green"
GOAL_COLOR = "red"

class Maze:
    def __init__(self, rows, cols):
        # 强制奇数行列以便回溯生成迷宫格子与墙对称
        self.rows = rows if rows % 2 == 1 else rows + 1
        self.cols = cols if cols % 2 == 1 else cols + 1
        # 0 表示墙，1 表示通路
        self.grid = [[0 for _ in range(self.cols)] for _ in range(self.rows)]
        self.generate()

    def generate(self):
        # 初始化：把所有单元设置为墙
        for r in range(self.rows):
            for c in range(self.cols):
                self.grid[r][c] = 0

        # 递归回溯生成迷宫（从(1,1)开始，步长为2）
        start = (1, 1)
        self.grid[start[0]][start[1]] = 1
        stack = [start]
        directions = [(0, 2), (0, -2), (2, 0), (-2, 0)]
        while stack:
            r, c = stack[-1]
            neighbors = []
            for dr, dc in directions:
                nr, nc = r + dr, c + dc
                if 1 <= nr < self.rows - 1 and 1 <= nc < self.cols - 1:
                    if self.grid[nr][nc] == 0:
                        neighbors.append((nr, nc, dr, dc))
            if neighbors:
                nr, nc, dr, dc = random.choice(neighbors)
                # 打通墙：中间的单元设为通路
                self.grid[r + dr // 2][c + dc // 2] = 1
                self.grid[nr][nc] = 1
                stack.append((nr, nc))
            else:
                stack.pop()

    def is_path(self, r, c):
        if 0 <= r < self.rows and 0 <= c < self.cols:
            return self.grid[r][c] == 1
        return False

class MazeApp:
    def __init__(self, master, rows=ROWS, cols=COLS, cell_size=CELL_SIZE):
        self.master = master
        self.rows = rows if rows % 2 == 1 else rows + 1
        self.cols = cols if cols % 2 == 1 else cols + 1
        self.cell_size = cell_size

        canvas_width = self.cols * self.cell_size
        canvas_height = self.rows * self.cell_size

        master.title("迷宫游戏")
        self.canvas = tk.Canvas(master, width=canvas_width, height=canvas_height, bg=PATH_COLOR)
        self.canvas.pack(side="top")

        # 状态栏：步数/时间/按钮
        self.status_frame = tk.Frame(master)
        self.status_frame.pack(fill="x", pady=5)
        self.steps_var = tk.StringVar(value="步数: 0")
        self.time_var = tk.StringVar(value="时间: 0.0 s")
        self.steps_label = tk.Label(self.status_frame, textvariable=self.steps_var)
        self.steps_label.pack(side="left", padx=6)
        self.time_label = tk.Label(self.status_frame, textvariable=self.time_var)
        self.time_label.pack(side="left", padx=6)

        self.btn_frame = tk.Frame(self.status_frame)
        self.btn_frame.pack(side="right")
        self.restart_btn = tk.Button(self.btn_frame, text="重新开始", command=self.restart)
        self.restart_btn.pack(side="left", padx=4)
        self.new_btn = tk.Button(self.btn_frame, text="生成新迷宫", command=self.new_maze)
        self.new_btn.pack(side="left", padx=4)

        # 生成迷宫与初始化玩家位置
        self.maze = Maze(self.rows, self.cols)
        self.player_r, self.player_c = 1, 1
        # 目标设在右下角可通路的位置
        self.goal_r, self.goal_c = self.rows - 2, self.cols - 2
        if not self.maze.is_path(self.goal_r, self.goal_c):
            # 如果目标位置是墙，寻找最近的通路
            for r in range(self.rows-2, 0, -1):
                for c in range(self.cols-2, 0, -1):
                    if self.maze.is_path(r, c):
                        self.goal_r, self.goal_c = r, c
                        break
                else:
                    continue
                break

        self.player_rect = None
        self.goal_rect = None

        self.steps = 0
        self.start_time = None
        self.running = False
        self.finished = False

        self.draw_maze()
        self.draw_player_and_goal()

        # 键绑定
        master.bind("<Up>", lambda e: self.move(-1, 0))
        master.bind("<Down>", lambda e: self.move(1, 0))
        master.bind("<Left>", lambda e: self.move(0, -1))
        master.bind("<Right>", lambda e: self.move(0, 1))
        # WASD 支持
        master.bind("w", lambda e: self.move(-1, 0))
        master.bind("s", lambda e: self.move(1, 0))
        master.bind("a", lambda e: self.move(0, -1))
        master.bind("d", lambda e: self.move(0, 1))

        # 每100ms更新计时显示
        self.update_clock()

    def draw_maze(self):
        self.canvas.delete("all")
        for r in range(self.rows):
            for c in range(self.cols):
                x0 = c * self.cell_size
                y0 = r * self.cell_size
                x1 = x0 + self.cell_size
                y1 = y0 + self.cell_size
                if self.maze.grid[r][c] == 0:
                    self.canvas.create_rectangle(x0, y0, x1, y1, fill=WALL_COLOR, outline=WALL_COLOR)
                else:
                    # 可选：画背景为 PATH_COLOR（canvas bg 已经是 PATH_COLOR），可以不画
                    pass

    def draw_player_and_goal(self):
        # 画目标
        if self.goal_rect:
            self.canvas.delete(self.goal_rect)
        gx0 = self.goal_c * self.cell_size + 2
        gy0 = self.goal_r * self.cell_size + 2
        gx1 = (self.goal_c + 1) * self.cell_size - 2
        gy1 = (self.goal_r + 1) * self.cell_size - 2
        self.goal_rect = self.canvas.create_rectangle(gx0, gy0, gx1, gy1, fill=GOAL_COLOR, outline="")

        # 画玩家
        if self.player_rect:
            self.canvas.delete(self.player_rect)
        px0 = self.player_c * self.cell_size + 4
        py0 = self.player_r * self.cell_size + 4
        px1 = (self.player_c + 1) * self.cell_size - 4
        py1 = (self.player_r + 1) * self.cell_size - 4
        self.player_rect = self.canvas.create_oval(px0, py0, px1, py1, fill=PLAYER_COLOR, outline="")

    def move(self, dr, dc):
        if self.finished:
            return
        nr = self.player_r + dr
        nc = self.player_c + dc
        # 边界和是否通路检测
        if 0 <= nr < self.rows and 0 <= nc < self.cols and self.maze.is_path(nr, nc):
            self.player_r, self.player_c = nr, nc
            self.steps += 1
            if not self.running:
                self.running = True
                self.start_time = time.time()
            self.steps_var.set(f"步数: {self.steps}")
            self.draw_player_and_goal()
            self.check_finish()

    def check_finish(self):
        if self.player_r == self.goal_r and self.player_c == self.goal_c:
            self.finished = True
            elapsed = time.time() - self.start_time if self.start_time else 0.0
            self.time_var.set(f"时间: {elapsed:.2f} s")
            # 弹窗显示结果
            tk.messagebox.showinfo("完成", f"到达终点！\n用时: {elapsed:.2f} 秒\n步数: {self.steps}")
            # 结束后仍显示最终时间
            self.running = False

    def update_clock(self):
        if self.running and not self.finished:
            elapsed = time.time() - self.start_time
            self.time_var.set(f"时间: {elapsed:.2f} s")
        self.master.after(100, self.update_clock)

    def restart(self):
        # 把玩家放回起点
        self.player_r, self.player_c = 1, 1
        # 如果起点不是通路则寻找第一个可通路位置
        if not self.maze.is_path(self.player_r, self.player_c):
            found = False
            for r in range(1, self.rows, 2):
                for c in range(1, self.cols, 2):
                    if self.maze.is_path(r, c):
                        self.player_r, self.player_c = r, c
                        found = True
                        break
                if found:
                    break
        self.steps = 0
        self.start_time = None
        self.running = False
        self.finished = False
        self.steps_var.set(f"步数: {self.steps}")
        self.time_var.set("时间: 0.0 s")
        self.draw_player_and_goal()

    def new_maze(self):
        self.maze = Maze(self.rows, self.cols)
        # 重设起点和终点
        self.player_r, self.player_c = 1, 1
        self.goal_r, self.goal_c = self.rows - 2, self.cols - 2
        if not self.maze.is_path(self.goal_r, self.goal_c):
            for r in range(self.rows-2, 0, -1):
                for c in range(self.cols-2, 0, -1):
                    if self.maze.is_path(r, c):
                        self.goal_r, self.goal_c = r, c
                        break
                else:
                    continue
                break
        self.restart()
        self.draw_maze()
        self.draw_player_and_goal()

if __name__ == "__main__":
    # 为了 messagebox 正常工作，需要导入子模块
    import tkinter.messagebox

    root = tk.Tk()
    # 可调整窗口大小和格子数
    app = MazeApp(root, rows=21, cols=21, cell_size=25)
    root.mainloop()