import tkinter as tk
from tkinter import ttk, messagebox
import random
import json
import os
from datetime import datetime

# 数据持久化文件
GAME_DATA_FILE = "tic_tac_toe_data.json"

class TicTacToeAI:
    def __init__(self, root):
        # 窗口基础设置
        self.root = root
        self.root.title("加强版井字棋 - AI人机对战")
        self.root.geometry("480x580")
        self.root.resizable(False, False)

        # 游戏核心数据
        self.board = [""] * 9  # 9格棋盘数据
        self.player = "X"      # 玩家棋子
        self.ai = "O"         # AI棋子
        self.game_over = False
        self.win_line = []    # 胜利连线位置

        # AI难度设置 1-简单 2-普通 3-困难
        self.ai_level = 2

        # 战绩统计数据
        self.win_count = 0
        self.lose_count = 0
        self.draw_count = 0

        # 加载本地历史战绩
        self.load_game_data()

        # 构建UI界面
        self.build_ui()
        # 刷新战绩显示
        self.update_score_text()

    # 加载历史战绩
    def load_game_data(self):
        if os.path.exists(GAME_DATA_FILE):
            with open(GAME_DATA_FILE, "r", encoding="utf-8") as f:
                data = json.load(f)
            self.win_count = data.get("win", 0)
            self.lose_count = data.get("lose", 0)
            self.draw_count = data.get("draw", 0)

    # 保存战绩数据
    def save_game_data(self):
        data = {
            "win": self.win_count,
            "lose": self.lose_count,
            "draw": self.draw_count,
            "last_play": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        }
        with open(GAME_DATA_FILE, "w", encoding="utf-8") as f:
            json.dump(data, f, ensure_ascii=False, indent=4)

    # 搭建界面
    def build_ui(self):
        # 标题标签
        tk.Label(self.root, text="加强版井字棋 人机对战", font=("微软雅黑", 22, "bold")).pack(pady=10)

        # 难度与战绩栏
        top_frame = tk.Frame(self.root)
        top_frame.pack(pady=5)

        # 难度选择
        tk.Label(top_frame, text="AI难度：", font=("微软雅黑", 11)).grid(row=0, column=0, padx=5)
        self.level_var = tk.StringVar(value="普通")
        level_combo = ttk.Combobox(top_frame, textvariable=self.level_var, width=8, font=("微软雅黑", 10))
        level_combo["values"] = ["简单", "普通", "困难"]
        level_combo.grid(row=0, column=1, padx=5)
        level_combo.bind("<<ComboboxSelected>>", self.change_level)

        # 战绩显示
        self.score_text = tk.Label(self.root, text="", font=("微软雅黑", 11), fg="#333")
        self.score_text.pack(pady=5)

        # 状态提示
        self.status_label = tk.Label(self.root, text="游戏就绪，点击棋盘开始对局", font=("微软雅黑", 12), fg="#2E8B57")
        self.status_label.pack(pady=8)

        # 棋盘框架
        self.board_frame = tk.Frame(self.root)
        self.board_frame.pack(pady=10)

        # 创建9个棋盘按钮
        self.buttons = []
        for i in range(9):
            btn = tk.Button(
                self.board_frame, text="", font=("微软雅黑", 30, "bold"),
                width=5, height=2, command=lambda idx=i: self.player_move(idx),
                relief=tk.RIDGE, bd=3
            )
            row = i // 3
            col = i % 3
            btn.grid(row=row, column=col, padx=2, pady=2)
            self.buttons.append(btn)

        # 功能按钮
        btn_frame = tk.Frame(self.root)
        btn_frame.pack(pady=20)
        tk.Button(btn_frame, text="重新开局", font=("微软雅黑", 12), width=10, command=self.reset_game, bg="#e8f4f8").grid(row=0, column=0, padx=10)
        tk.Button(btn_frame, text="清空战绩", font=("微软雅黑", 12), width=10, command=self.clear_score, bg="#fff2e8").grid(row=0, column=1, padx=10)

    # 切换AI难度
    def change_level(self, event):
        level = self.level_var.get()
        if level == "简单":
            self.ai_level = 1
        elif level == "普通":
            self.ai_level = 2
        else:
            self.ai_level = 3
        self.status_label.config(text=f"已切换为{level}难度，可随时开局")

    # 更新战绩显示
    def update_score_text(self):
        self.score_text.config(text=f"战绩统计：胜利{self.win_count}局 | 失败{self.lose_count}局 | 平局{self.draw_count}局")

    # 玩家落子
    def player_move(self, idx):
        # 游戏结束/已有棋子则无效
        if self.game_over or self.board[idx] != "":
            return

        # 玩家落子
        self.board[idx] = self.player
        self.buttons[idx].config(text=self.player, fg="#2E8B57", bg="#f0fff4")
        self.status_label.config(text="AI思考中...", fg="#FF8C00")

        # 判断玩家是否胜利
        if self.check_win(self.player):
            self.game_over = True
            self.win_count += 1
            self.show_win_effect()
            self.save_game_data()
            self.update_score_text()
            self.status_label.config(text="恭喜！你赢得了对局！", fg="#2E8B57")
            messagebox.showinfo("游戏胜利", "恭喜你战胜AI！")
            return

        # 判断平局
        if self.check_draw():
            self.game_over = True
            self.draw_count += 1
            self.save_game_data()
            self.update_score_text()
            self.status_label.config(text="对局结束，平局！", fg="#444444")
            messagebox.showinfo("游戏结束", "势均力敌，平局！")
            return

        # AI延迟落子，模拟思考
        self.root.after(400, self.ai_move)

    # AI智能落子（分难度算法）
    def ai_move(self):
        # 简单难度：30%概率随机落子，AI变笨
        if self.ai_level == 1 and random.random() < 0.3:
            empty_pos = [i for i in range(9) if self.board[i] == ""]
            pos = random.choice(empty_pos)
            self.board[pos] = self.ai
            self.buttons[pos].config(text=self.ai, fg="#FF4500", bg="#fff0f0")
            self.check_ai_result()
            return

        # 困难难度：完美AI，无失误
        # 1. AI优先直接赢棋
        for i in range(9):
            if self.board[i] == "":
                self.board[i] = self.ai
                if self.check_win(self.ai):
                    self.buttons[i].config(text=self.ai, fg="#FF4500", bg="#fff0f0")
                    self.game_over = True
                    self.lose_count += 1
                    self.show_win_effect()
                    self.save_game_data()
                    self.update_score_text()
                    self.status_label.config(text="AI获胜，再接再厉！", fg="#FF4500")
                    messagebox.showinfo("游戏结束", "AI获胜！再接再厉！")
                    return
                self.board[i] = ""

        # 2. AI防守：阻止玩家赢棋（普通/困难难度生效）
        if self.ai_level >= 2:
            for i in range(9):
                if self.board[i] == "":
                    self.board[i] = self.player
                    if self.check_win(self.player):
                        self.board[i] = self.ai
                        self.buttons[i].config(text=self.ai, fg="#FF4500", bg="#fff0f0")
                        self.check_ai_result()
                        return
                    self.board[i] = ""

        # 3. 抢占关键位置
        priority = [4, 0, 2, 6, 8, 1, 3, 5, 7]
        for idx in priority:
            if self.board[idx] == "":
                self.board[idx] = self.ai
                self.buttons[idx].config(text=self.ai, fg="#FF4500", bg="#fff0f0")
                break

        self.check_ai_result()

    # 检测AI落子后的对局结果
    def check_ai_result(self):
        # 判断平局
        if self.check_draw():
            self.game_over = True
            self.draw_count += 1
            self.save_game_data()
            self.update_score_text()
            self.status_label.config(text="对局结束，平局！", fg="#444444")
            messagebox.showinfo("游戏结束", "势均力敌，平局！")

    # 胜利高亮特效
    def show_win_effect(self):
        if not self.win_line:
            return
        for idx in self.win_line:
            self.buttons[idx].config(bg="#ffe600")

    # 判断胜利，记录胜利连线
    def check_win(self, chess):
        # 所有获胜组合
        win_list = [
            [0,1,2], [3,4,5], [6,7,8],  # 横向
            [0,3,6], [1,4,7], [2,5,8],  # 纵向
            [0,4,8], [2,4,6]             # 斜线
        ]
        for item in win_list:
            if self.board[item[0]] == self.board[item[1]] == self.board[item[2]] == chess:
                self.win_line = item
                return True
        self.win_line = []
        return False

    # 判断平局
    def check_draw(self):
        return "" not in self.board

    # 重置游戏
    def reset_game(self):
        self.board = [""] * 9
        self.game_over = False
        self.win_line = []
        for btn in self.buttons:
            btn.config(text="", bg="#f5f5f5")
        self.status_label.config(text="游戏就绪，点击棋盘开始对局", fg="#2E8B57")

    # 清空战绩
    def clear_score(self):
        if not messagebox.askyesno("确认清空", "确定要清空所有历史战绩吗？数据不可恢复！"):
            return
        self.win_count = 0
        self.lose_count = 0
        self.draw_count = 0
        self.save_game_data()
        self.update_score_text()
        messagebox.showinfo("操作成功", "所有战绩已清空！")

if __name__ == "__main__":
    root = tk.Tk()
    game = TicTacToeAI(root)
    root.mainloop()
