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

class IdiomGame:
    def __init__(self, root):
        self.root = root
        self.root.title("成语接龙 v1.0")
        self.root.geometry("900x700")
        self.root.configure(bg='#F5F5F5')
        
        # 加载成语库
        self.idioms = self.load_idioms()
        
        # 游戏状态
        self.current_idiom = ""
        self.game_history = []
        self.used_idioms = set()
        self.player_score = 0
        self.computer_score = 0
        self.game_mode = "单人"  # 单人/双人
        self.difficulty = "中等"  # 简单/中等/困难
        self.game_started = False
        
        # 初始化界面
        self.setup_ui()
        
        # 加载游戏记录
        self.load_game_record()
    
    def load_idioms(self):
        """加载成语库"""
        idioms = [
            "一马当先", "先发制人", "人山人海", "海阔天空", "空穴来风",
            "风花雪月", "月明星稀", "稀奇古怪", "怪力乱神", "神采飞扬",
            "扬眉吐气", "气壮山河", "河东狮吼", "吼天喊地", "地大物博",
            "博学多才", "才高八斗", "斗转星移", "移花接木", "木已成舟",
            "舟车劳顿", "顿开茅塞", "塞翁失马", "马到成功", "功成名就",
            "就事论事", "事在人为", "为所欲为", "为富不仁", "仁至义尽",
            "尽善尽美", "美中不足", "足智多谋", "谋事在人", "人定胜天",
            "天经地义", "义不容辞", "辞旧迎新", "新陈代谢", "谢天谢地",
            "地老天荒", "荒诞不经", "经天纬地", "地动山摇", "摇旗呐喊",
            "喊冤叫屈", "屈指可数", "数一数二", "二龙戏珠", "珠光宝气",
            "气象万千", "千军万马", "马不停蹄", "蹄间三寻", "寻根问底",
            "底死谩生", "生龙活虎", "虎头蛇尾", "尾大不掉", "掉以轻心",
            "心旷神怡", "怡然自得", "得心应手", "手不释卷", "卷土重来",
            "来日方长", "长治久安", "安步当车", "车水马龙", "龙马精神",
            "神机妙算", "算无遗策", "策马奔腾", "腾云驾雾", "雾里看花",
            "花好月圆", "圆木警枕", "枕戈待旦", "旦夕之间", "间不容发",
            "发愤图强", "强词夺理", "理直气壮", "壮志凌云", "云开见日",
            "日新月异", "异想天开", "开门见山", "山清水秀", "秀外慧中",
            "中流砥柱", "柱石之坚", "坚不可摧", "摧枯拉朽", "朽木粪土"
        ]
        
        # 按首字分组
        self.idiom_dict = {}
        for idiom in idioms:
            first_char = idiom[0]
            if first_char not in self.idiom_dict:
                self.idiom_dict[first_char] = []
            self.idiom_dict[first_char].append(idiom)
        
        return idioms
    
    def setup_ui(self):
        """设置用户界面"""
        # 标题
        title_frame = tk.Frame(self.root, bg='#4A90E2', height=80)
        title_frame.pack(fill='x', pady=(0, 20))
        title_frame.pack_propagate(False)
        
        title_label = tk.Label(
            title_frame,
            text="成语接龙",
            font=('微软雅黑', 28, 'bold'),
            fg='white',
            bg='#4A90E2'
        )
        title_label.pack(expand=True)
        
        # 主容器
        main_container = tk.Frame(self.root, bg='#F5F5F5')
        main_container.pack(fill='both', expand=True, padx=30, pady=10)
        
        # 左侧面板 - 游戏控制
        left_panel = tk.Frame(main_container, bg='#FFFFFF', width=250, 
                             relief='ridge', bd=2)
        left_panel.pack(side='left', fill='y', padx=(0, 20))
        left_panel.pack_propagate(False)
        
        # 右侧面板 - 游戏区域
        right_panel = tk.Frame(main_container, bg='#FFFFFF', 
                              relief='ridge', bd=2)
        right_panel.pack(side='left', fill='both', expand=True)
        
        # 左侧面板内容
        self.setup_left_panel(left_panel)
        
        # 右侧面板内容
        self.setup_right_panel(right_panel)
    
    def setup_left_panel(self, panel):
        """设置左侧控制面板"""
        # 控制面板标题
        control_title = tk.Label(
            panel,
            text="游戏控制",
            font=('微软雅黑', 16, 'bold'),
            bg='#FFFFFF',
            fg='#333333',
            pady=15
        )
        control_title.pack(fill='x')
        
        # 游戏模式选择
        mode_frame = tk.Frame(panel, bg='#FFFFFF')
        mode_frame.pack(fill='x', padx=20, pady=10)
        
        tk.Label(mode_frame, text="游戏模式:", 
                font=('微软雅黑', 12), bg='#FFFFFF').pack(anchor='w')
        
        self.mode_var = tk.StringVar(value=self.game_mode)
        mode_combobox = ttk.Combobox(
            mode_frame,
            textvariable=self.mode_var,
            values=["单人", "双人"],
            state="readonly",
            width=20,
            font=('微软雅黑', 11)
        )
        mode_combobox.pack(pady=5)
        mode_combobox.bind("<<ComboboxSelected>>", self.change_mode)
        
        # 难度选择
        difficulty_frame = tk.Frame(panel, bg='#FFFFFF')
        difficulty_frame.pack(fill='x', padx=20, pady=10)
        
        tk.Label(difficulty_frame, text="游戏难度:", 
                font=('微软雅黑', 12), bg='#FFFFFF').pack(anchor='w')
        
        self.difficulty_var = tk.StringVar(value=self.difficulty)
        difficulty_combobox = ttk.Combobox(
            difficulty_frame,
            textvariable=self.difficulty_var,
            values=["简单", "中等", "困难"],
            state="readonly",
            width=20,
            font=('微软雅黑', 11)
        )
        difficulty_combobox.pack(pady=5)
        difficulty_combobox.bind("<<ComboboxSelected>>", self.change_difficulty)
        
        # 开始游戏按钮
        start_button = tk.Button(
            panel,
            text="开始游戏",
            command=self.start_game,
            font=('微软雅黑', 13, 'bold'),
            bg='#4CAF50',
            fg='white',
            width=20,
            height=2,
            relief='flat',
            cursor='hand2'
        )
        start_button.pack(pady=20)
        
        # 重新开始按钮
        restart_button = tk.Button(
            panel,
            text="重新开始",
            command=self.restart_game,
            font=('微软雅黑', 12),
            bg='#2196F3',
            fg='white',
            width=20,
            height=1,
            relief='flat',
            cursor='hand2'
        )
        restart_button.pack(pady=5)
        
        # 提示按钮
        hint_button = tk.Button(
            panel,
            text="获取提示",
            command=self.give_hint,
            font=('微软雅黑', 12),
            bg='#FF9800',
            fg='white',
            width=20,
            height=1,
            relief='flat',
            cursor='hand2'
        )
        hint_button.pack(pady=5)
        
        # 游戏规则按钮
        rule_button = tk.Button(
            panel,
            text="游戏规则",
            command=self.show_rules,
            font=('微软雅黑', 12),
            bg='#9C27B0',
            fg='white',
            width=20,
            height=1,
            relief='flat',
            cursor='hand2'
        )
        rule_button.pack(pady=5)
        
        # 退出游戏按钮
        exit_button = tk.Button(
            panel,
            text="退出游戏",
            command=self.root.quit,
            font=('微软雅黑', 12),
            bg='#F44336',
            fg='white',
            width=20,
            height=1,
            relief='flat',
            cursor='hand2'
        )
        exit_button.pack(pady=5)
        
        # 分数显示
        score_frame = tk.Frame(panel, bg='#FFFFFF')
        score_frame.pack(fill='x', padx=20, pady=20)
        
        self.player_score_label = tk.Label(
            score_frame,
            text="玩家: 0 分",
            font=('微软雅黑', 12, 'bold'),
            bg='#FFFFFF',
            fg='#2196F3'
        )
        self.player_score_label.pack(anchor='w', pady=5)
        
        self.computer_score_label = tk.Label(
            score_frame,
            text="电脑: 0 分",
            font=('微软雅黑', 12, 'bold'),
            bg='#FFFFFF',
            fg='#FF5722'
        )
        self.computer_score_label.pack(anchor='w')
        
        # 当前接龙尾字
        self.last_char_label = tk.Label(
            panel,
            text="接龙尾字: 无",
            font=('微软雅黑', 12),
            bg='#FFFFFF',
            fg='#4CAF50'
        )
        self.last_char_label.pack(pady=10)
        
        # 游戏记录
        record_frame = tk.Frame(panel, bg='#FFFFFF')
        record_frame.pack(fill='both', expand=True, padx=20, pady=10)
        
        tk.Label(record_frame, text="游戏记录:", 
                font=('微软雅黑', 12, 'bold'), bg='#FFFFFF').pack(anchor='w')
        
        self.record_listbox = tk.Listbox(
            record_frame,
            height=8,
            font=('微软雅黑', 10),
            bg='#F8F9FA',
            relief='flat'
        )
        self.record_listbox.pack(fill='both', expand=True, pady=5)
    
    def setup_right_panel(self, panel):
        """设置右侧游戏面板"""
        # 当前成语显示区域
        current_frame = tk.Frame(panel, bg='#E3F2FD', height=150)
        current_frame.pack(fill='x', pady=20, padx=20)
        current_frame.pack_propagate(False)
        
        tk.Label(
            current_frame,
            text="当前成语",
            font=('微软雅黑', 14, 'bold'),
            bg='#E3F2FD',
            fg='#1565C0'
        ).pack(pady=(20, 10))
        
        self.current_idiom_label = tk.Label(
            current_frame,
            text="等待游戏开始...",
            font=('楷体', 36, 'bold'),
            bg='#E3F2FD',
            fg='#0D47A1',
            height=2
        )
        self.current_idiom_label.pack(expand=True)
        
        # 历史记录区域
        history_frame = tk.Frame(panel, bg='#F5F5F5')
        history_frame.pack(fill='both', expand=True, padx=20, pady=10)
        
        tk.Label(
            history_frame,
            text="成语接龙历史",
            font=('微软雅黑', 14, 'bold'),
            bg='#F5F5F5',
            fg='#333333'
        ).pack(anchor='w', pady=(0, 10))
        
        # 历史记录文本框
        self.history_text = tk.Text(
            history_frame,
            height=12,
            font=('微软雅黑', 12),
            bg='white',
            relief='solid',
            bd=1,
            wrap='word'
        )
        self.history_text.pack(fill='both', expand=True)
        
        scrollbar = tk.Scrollbar(self.history_text)
        scrollbar.pack(side='right', fill='y')
        self.history_text.config(yscrollcommand=scrollbar.set)
        scrollbar.config(command=self.history_text.yview)
        
        # 输入区域
        input_frame = tk.Frame(panel, bg='#FFFFFF', height=100)
        input_frame.pack(fill='x', padx=20, pady=20)
        input_frame.pack_propagate(False)
        
        tk.Label(
            input_frame,
            text="请输入成语:",
            font=('微软雅黑', 12),
            bg='#FFFFFF'
        ).pack(anchor='w', pady=(10, 5))
        
        input_container = tk.Frame(input_frame, bg='#FFFFFF')
        input_container.pack(fill='x', pady=5)
        
        self.idiom_var = tk.StringVar()
        self.idiom_entry = tk.Entry(
            input_container,
            textvariable=self.idiom_var,
            font=('微软雅黑', 14),
            width=25,
            relief='solid',
            bd=2
        )
        self.idiom_entry.pack(side='left', padx=(0, 10))
        self.idiom_entry.bind('<Return>', lambda e: self.submit_idiom())
        
        submit_button = tk.Button(
            input_container,
            text="提交",
            command=self.submit_idiom,
            font=('微软雅黑', 12, 'bold'),
            bg='#4CAF50',
            fg='white',
            width=10,
            height=1,
            relief='flat',
            cursor='hand2'
        )
        submit_button.pack(side='left')
        
        # 状态栏
        self.status_label = tk.Label(
            panel,
            text="就绪",
            font=('微软雅黑', 10),
            bg='#EEEEEE',
            fg='#666666',
            anchor='w',
            height=2
        )
        self.status_label.pack(fill='x', side='bottom', padx=20, pady=(0, 10))
    
    def change_mode(self, event):
        """更改游戏模式"""
        self.game_mode = self.mode_var.get()
        self.update_status(f"游戏模式已切换为: {self.game_mode}")
    
    def change_difficulty(self, event):
        """更改游戏难度"""
        self.difficulty = self.difficulty_var.get()
        self.update_status(f"游戏难度已切换为: {self.difficulty}")
    
    def start_game(self):
        """开始游戏"""
        if not self.game_started:
            # 选择起始成语
            self.current_idiom = random.choice(self.idioms)
            self.used_idioms.add(self.current_idiom)
            self.game_history = [self.current_idiom]
            
            # 更新显示
            self.update_display()
            self.game_started = True
            
            # 更新状态
            self.update_status("游戏开始！请接龙...")
            
            # 如果是单人模式，电脑先手
            if self.game_mode == "单人":
                self.root.after(1000, self.computer_turn)
    
    def restart_game(self):
        """重新开始游戏"""
        self.current_idiom = ""
        self.game_history = []
        self.used_idioms.clear()
        self.player_score = 0
        self.computer_score = 0
        self.game_started = False
        
        # 更新显示
        self.update_display()
        self.update_scores()
        
        # 清除历史记录
        self.history_text.delete(1.0, tk.END)
        self.record_listbox.delete(0, tk.END)
        
        self.update_status("游戏已重置，点击'开始游戏'开始新游戏")
    
    def submit_idiom(self):
        """提交成语"""
        if not self.game_started:
            messagebox.showwarning("警告", "请先开始游戏！")
            return
        
        idiom = self.idiom_var.get().strip()
        if not idiom:
            messagebox.showwarning("警告", "请输入成语！")
            return
        
        # 验证成语
        if not self.is_valid_idiom(idiom):
            messagebox.showwarning("无效成语", "请输入一个有效的四字成语！")
            self.idiom_var.set("")
            return
        
        if idiom in self.used_idioms:
            messagebox.showwarning("重复成语", "这个成语已经用过了！")
            self.idiom_var.set("")
            return
        
        # 验证接龙规则
        if not self.check_chain_rule(idiom):
            last_char = self.get_last_char(self.current_idiom)
            messagebox.showwarning("接龙错误", 
                f"请以'{last_char}'开头的成语接龙！")
            self.idiom_var.set("")
            return
        
        # 有效成语
        self.player_score += 1
        self.current_idiom = idiom
        self.used_idioms.add(idiom)
        self.game_history.append(f"玩家: {idiom}")
        
        # 更新显示
        self.update_display()
        self.update_scores()
        self.add_to_record(f"玩家: {idiom}")
        
        # 添加到历史记录
        self.add_to_history(f"玩家 → {idiom}")
        
        # 检查游戏是否结束
        if self.check_game_over():
            return
        
        # 如果是单人模式，电脑回合
        if self.game_mode == "单人":
            self.idiom_var.set("")
            self.root.after(1000, self.computer_turn)
        else:
            self.idiom_var.set("")
            self.update_status("接龙成功！轮到下一位玩家")
    
    def computer_turn(self):
        """电脑回合"""
        if not self.game_started:
            return
        
        last_char = self.get_last_char(self.current_idiom)
        
        # 根据难度选择策略
        if self.difficulty == "简单":
            idiom = self.find_computer_idiom_simple(last_char)
        elif self.difficulty == "困难":
            idiom = self.find_computer_idiom_hard(last_char)
        else:  # 中等难度
            idiom = self.find_computer_idiom_medium(last_char)
        
        if idiom:
            self.computer_score += 1
            self.current_idiom = idiom
            self.used_idioms.add(idiom)
            self.game_history.append(f"电脑: {idiom}")
            
            # 更新显示
            self.update_display()
            self.update_scores()
            self.add_to_record(f"电脑: {idiom}")
            
            # 添加到历史记录
            self.add_to_history(f"电脑 → {idiom}")
            
            # 检查游戏是否结束
            if self.check_game_over():
                return
            
            self.update_status("电脑已完成接龙，轮到你了！")
        else:
            # 电脑无法接龙，玩家获胜
            messagebox.showinfo("游戏结束", "电脑无法接龙，你赢了！")
            self.save_game_record("玩家获胜")
            self.game_started = False
    
    def find_computer_idiom_simple(self, last_char):
        """简单难度 - 随机选择一个可用成语"""
        if last_char in self.idiom_dict:
            available = [i for i in self.idiom_dict[last_char] 
                        if i not in self.used_idioms]
            if available:
                return random.choice(available)
        return None
    
    def find_computer_idiom_medium(self, last_char):
        """中等难度 - 优先选择让对手难接的成语"""
        if last_char in self.idiom_dict:
            available = [i for i in self.idiom_dict[last_char] 
                        if i not in self.used_idioms]
            if available:
                # 选择尾字不常见开头的成语
                scored_idioms = []
                for idiom in available:
                    next_char = idiom[-1]
                    # 计算这个尾字的可用成语数量
                    if next_char in self.idiom_dict:
                        next_available = len([i for i in self.idiom_dict[next_char] 
                                            if i not in self.used_idioms])
                        # 分数越低越好（可用成语越少）
                        scored_idioms.append((idiom, next_available))
                
                if scored_idioms:
                    # 选择分数最低的（最难接的）
                    scored_idioms.sort(key=lambda x: x[1])
                    return scored_idioms[0][0]
                else:
                    return random.choice(available)
        return None
    
    def find_computer_idiom_hard(self, last_char):
        """困难难度 - 使用更复杂的策略"""
        return self.find_computer_idiom_medium(last_char)  # 简化为中等难度
    
    def is_valid_idiom(self, idiom):
        """验证是否为有效成语"""
        # 基本验证：长度为4，都是汉字
        if len(idiom) != 4:
            return False
        
        for char in idiom:
            if not '\u4e00' <= char <= '\u9fff':
                return False
        
        # 检查是否在成语库中
        return idiom in self.idioms
    
    def check_chain_rule(self, new_idiom):
        """检查接龙规则"""
        if not self.current_idiom:  # 第一个成语
            return True
        
        last_char = self.get_last_char(self.current_idiom)
        return new_idiom[0] == last_char
    
    def get_last_char(self, idiom):
        """获取成语的最后一个字"""
        return idiom[-1] if idiom else ""
    
    def check_game_over(self):
        """检查游戏是否结束"""
        if len(self.game_history) >= 20:  # 最大轮数
            winner = "玩家" if self.player_score > self.computer_score else "电脑"
            if self.player_score == self.computer_score:
                messagebox.showinfo("游戏结束", f"平局！最终比分：{self.player_score}:{self.computer_score}")
            else:
                messagebox.showinfo("游戏结束", f"{winner}获胜！最终比分：{self.player_score}:{self.computer_score}")
            
            self.save_game_record(f"{winner}获胜 ({self.player_score}:{self.computer_score})")
            self.game_started = False
            return True
        
        # 检查是否还有可用成语
        last_char = self.get_last_char(self.current_idiom)
        if last_char in self.idiom_dict:
            available = [i for i in self.idiom_dict[last_char] 
                        if i not in self.used_idioms]
            if not available:
                winner = "玩家" if self.player_score > self.computer_score else "电脑"
                messagebox.showinfo("游戏结束", f"无可用成语！{winner}获胜！")
                self.save_game_record(f"{winner}获胜 (无可用成语)")
                self.game_started = False
                return True
        
        return False
    
    def update_display(self):
        """更新显示"""
        self.current_idiom_label.config(text=self.current_idiom or "等待游戏开始...")
        
        # 更新尾字显示
        if self.current_idiom:
            last_char = self.get_last_char(self.current_idiom)
            self.last_char_label.config(text=f"接龙尾字: {last_char}")
        else:
            self.last_char_label.config(text="接龙尾字: 无")
    
    def update_scores(self):
        """更新分数显示"""
        self.player_score_label.config(text=f"玩家: {self.player_score} 分")
        self.computer_score_label.config(text=f"电脑: {self.computer_score} 分")
    
    def add_to_history(self, text):
        """添加到历史记录"""
        self.history_text.insert(tk.END, text + "\n")
        self.history_text.see(tk.END)
    
    def add_to_record(self, record):
        """添加到游戏记录列表"""
        timestamp = datetime.now().strftime("%H:%M:%S")
        self.record_listbox.insert(tk.END, f"[{timestamp}] {record}")
        self.record_listbox.see(tk.END)
    
    def update_status(self, message):
        """更新状态栏"""
        self.status_label.config(text=f"状态: {message}")
    
    def give_hint(self):
        """给出提示"""
        if not self.game_started or not self.current_idiom:
            messagebox.showinfo("提示", "请先开始游戏！")
            return
        
        last_char = self.get_last_char(self.current_idiom)
        if last_char in self.idiom_dict:
            available = [i for i in self.idiom_dict[last_char] 
                        if i not in self.used_idioms]
            if available:
                hint = random.choice(available[:3])  # 随机选择一个提示
                messagebox.showinfo("提示", f"你可以尝试: {hint}")
            else:
                messagebox.showinfo("提示", "没有可用的成语了！")
        else:
            messagebox.showinfo("提示", "没有可用的成语了！")
    
    def show_rules(self):
        """显示游戏规则"""
        rules = """成语接龙游戏规则：

1. 游戏开始时，系统随机选择一个成语
2. 玩家需要说出一个成语，其首字需与上一个成语的尾字相同
3. 每个成语只能使用一次
4. 成语必须是标准的四字成语
5. 无法接龙或使用重复成语者失败

计分规则：
- 每次成功接龙得1分
- 游戏进行20轮或一方无法接龙时结束
- 分数高者获胜

游戏模式：
- 单人模式：与电脑对战
- 双人模式：两位玩家轮流对战

祝您游戏愉快！"""
        
        messagebox.showinfo("游戏规则", rules)
    
    def save_game_record(self, result):
        """保存游戏记录"""
        try:
            record = {
                "date": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
                "mode": self.game_mode,
                "difficulty": self.difficulty,
                "player_score": self.player_score,
                "computer_score": self.computer_score,
                "result": result,
                "history": self.game_history
            }
            
            # 这里可以添加保存到文件的代码
            # 例如：保存到JSON文件或数据库
            self.add_to_record(f"游戏结束: {result}")
            
        except Exception as e:
            print(f"保存记录失败: {e}")
    
    def load_game_record(self):
        """加载游戏记录"""
        # 这里可以添加从文件加载记录的代码
        pass

def main():
    root = tk.Tk()
    app = IdiomGame(root)
    
    # 设置窗口居中
    root.update_idletasks()
    width = root.winfo_width()
    height = root.winfo_height()
    x = (root.winfo_screenwidth() // 2) - (width // 2)
    y = (root.winfo_screenheight() // 2) - (height // 2)
    root.geometry(f'{width}x{height}+{x}+{y}')
    
    root.mainloop()

if __name__ == "__main__":
    main()