"""
╔══════════════════════════════════════════════════╗
║           成语接龙游戏 - Pygame 精美版           ║
╠══════════════════════════════════════════════════╣
║  🎮 电脑先出一个成语，玩家接龙                  ║
║  📝 下一个成语的首字拼音 = 上一个成语的尾字拼音  ║
║  🔊 支持同音字接龙                               ║
║  💡 提供提示功能（扣分）                         ║
║  🏆 连击越多得分越高                             ║
╚══════════════════════════════════════════════════╝
"""

import pygame
import sys
import random
import os
import math
from pypinyin import pinyin, Style

# ==================== 初始化 ====================
pygame.init()
pygame.mixer.init()

# ==================== 常量配置 ====================
SCREEN_WIDTH = 1000
SCREEN_HEIGHT = 720
FPS = 60

# 配色方案 - 深色科技风
BG_COLOR       = (22, 26, 45)
PANEL_BG       = (32, 40, 68)
INPUT_BG       = (42, 52, 82)
BTN_PRIMARY    = (65, 130, 200)
BTN_HOVER      = (85, 160, 230)
BTN_ACTIVE     = (45, 100, 170)
BTN_SUCCESS    = (55, 160, 100)
BTN_SUCCESS_H  = (75, 190, 130)
BTN_WARNING    = (180, 120, 50)
BTN_WARNING_H  = (210, 150, 70)
BTN_DANGER     = (180, 60, 60)
BTN_DANGER_H   = (210, 85, 85)

TEXT_COLOR     = (225, 230, 245)
TEXT_DIM       = (140, 150, 175)
ACCENT_GOLD    = (255, 200, 70)
ACCENT_GREEN   = (70, 215, 120)
ACCENT_RED     = (235, 75, 75)
ACCENT_BLUE    = (100, 180, 255)
ACCENT_PURPLE  = (180, 130, 240)
CHAIN_TAG_PC   = (100, 200, 170)
CHAIN_TAG_HUMAN = (255, 190, 80)

# ==================== 字体工具 ====================
def get_font(size, bold=False):
    """获取中文字体"""
    paths = [
        "/usr/share/fonts/truetype/wqy/wqy-microhei.ttc",
        "/usr/share/fonts/wenquanyi/wqy-microhei/wqy-microhei.ttc",
        "/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc",
    ]
    for fp in paths:
        if os.path.exists(fp):
            return pygame.font.Font(fp, size)
    return pygame.font.SysFont("microhei", size, bold=bold)

# ==================== 成语数据库 ====================
CHENGYU_DATA = [
    # ---- 一画起 ----
    "一心一意", "一鸣惊人", "一石二鸟", "一帆风顺", "一箭双雕",
    "一鼓作气", "一举两得", "一日千里", "一望无际", "一尘不染",
    "一毛不拔", "一窍不通", "一视同仁", "一泻千里", "一表人才",
    "一意孤行", "一模一样", "一筹莫展", "一针见血", "一知半解",
    "一本正经", "一气呵成", "一落千丈", "一见钟情", "一往无前",
    "一无所有", "一如既往", "一举成名", "一败涂地", "一臂之力",
    "一丝不苟", "一诺千金", "一暴十寒", "一窍不通", "一视同仁",

    # ---- 二画起 ----
    "二话不说", "二三其德", "二龙戏珠", "两面三刀", "两全其美",
    "两袖清风", "两肋插刀", "两小无猜", "两败俱伤",

    # ---- 三画起 ----
    "三心二意", "三言两语", "三长两短", "三顾茅庐", "三阳开泰",
    "三令五申", "三思而行", "三头六臂", "三更半夜", "三教九流",
    "三番五次", "三言两语", "三生有幸", "三足鼎立",

    # ---- 四画起 ----
    "四通八达", "四面楚歌", "四海为家", "四平八稳", "四分五裂",
    "四面八方", "四书五经",

    # ---- 五画起 ----
    "五湖四海", "五光十色", "五颜六色", "五花八门", "五体投地",
    "五光十色", "五雷轰顶",

    # ---- 六画起 ----
    "六神无主", "六亲不认",

    # ---- 七画起 ----
    "七上八下", "七嘴八舌", "七手八脚", "七窍生烟", "七零八落",

    # ---- 八画起 ----
    "八面玲珑", "八仙过海",

    # ---- 九画起 ----
    "九牛一毛", "九死一生", "九牛二虎",

    # ---- 十画起 ----
    "十全十美", "十拿九稳", "十万火急",

    # ---- 百千万 ----
    "百发百中", "百花齐放", "百家争鸣", "百战百胜", "百折不挠",
    "百无聊赖", "百思不解", "百读不厌", "百感交集",
    "千军万马", "千变万化", "千钧一发", "千言万语", "千秋万代",
    "千辛万苦", "千真万确", "千奇百怪", "千篇一律",
    "万紫千红", "万水千山", "万古长青", "万众一心", "万象更新",
    "万无一失", "万籁俱寂",

    # ---- A ----
    "爱不释手", "爱屋及乌", "安居乐业", "安分守己", "安之若素",
    "安然无恙", "安邦定国", "安身立命",

    # ---- B ----
    "拔苗助长", "白手起家", "百折不挠", "班门弄斧", "半途而废",
    "包罗万象", "饱经风霜", "抱头鼠窜", "暴跳如雷", "杯弓蛇影",
    "悲欢离合", "背道而驰", "本末倒置", "笨鸟先飞", "逼上梁山",
    "比比皆是", "笔走龙蛇", "闭门造车", "别出心裁", "别有用心",
    "冰天雪地", "兵强马壮", "病入膏肓", "拨云见日", "博古通今",
    "博大精深", "不卑不亢", "不耻下问", "不出所料", "不动声色",
    "不共戴天", "不寒而栗", "不欢而散", "不惑之年", "不急之务",
    "不假思索", "不胫而走", "不堪回首", "不可救药", "不可思议",
    "不劳而获", "不露声色", "不毛之地", "不谋而合", "不偏不倚",
    "不期而遇", "不切实际", "不三不四", "不速之客", "不闻不问",
    "不学无术", "不言而喻", "不遗余力", "不亦乐乎", "不约而同",
    "不自量力", "不知所措", "不足为奇",

    # ---- C ----
    "才高八斗", "残羹冷炙", "沧海桑田", "沧海一粟", "藏龙卧虎",
    "草木皆兵", "层出不穷", "差强人意", "察言观色", "姹紫嫣红",
    "馋涎欲滴", "长驱直入", "长篇大论", "长篇累牍", "畅所欲言",
    "车水马龙", "称心如意", "趁热打铁", "瞠目结舌", "成家立业",
    "成竹在胸", "诚心诚意", "承前启后", "惩前毖后", "痴心妄想",
    "痴心妄想", "迟疑不决", "持之以恒", "赤膊上阵", "赤手空拳",
    "冲锋陷阵", "崇山峻岭", "愁眉苦脸", "踌躇满志", "丑态百出",
    "出类拔萃", "出谋划策", "出生入死", "出言不逊", "除暴安良",
    "处心积虑", "触景生情", "触类旁通", "川流不息", "穿针引线",
    "串通一气", "吹毛求疵", "垂头丧气", "唇亡齿寒", "此起彼伏",
    "从容不迫", "从头至尾", "粗枝大叶", "促膝谈心", "寸步难行",
    "措手不及",

    # ---- D ----
    "打草惊蛇", "大材小用", "大公无私", "大惊小怪", "大开眼界",
    "大快人心", "大同小异", "大显身手", "大相径庭", "大言不惭",
    "大义凛然", "大智若愚", "呆若木鸡", "待人接物", "当务之急",
    "当之无愧", "党同伐异", "道貌岸然", "道听途说", "得不偿失",
    "得寸进尺", "得过且过", "得心应手", "得意忘形", "得意洋洋",
    "德高望重", "登峰造极", "等量齐观", "低头折节", "地大物博",
    "地动山摇", "颠倒黑白", "颠沛流离", "雕虫小技", "调虎离山",
    "顶天立地", "东奔西走", "东倒西歪", "东拉西扯", "东山再起",
    "东施效颦", "动人心弦", "洞若观火", "斗志昂扬", "独断专行",
    "独树一帜", "独一无二", "杜门不出", "断章取义", "对症下药",
    "夺眶而出", "多才多艺", "多此一举", "多多益善", "多谋善断",

    # ---- E ----
    "阿谀奉承", "婀娜多姿", "耳目一新", "耳濡目染", "耳熟能详",
    "发愤图强", "发扬光大", "翻江倒海", "翻天覆地", "繁花似锦",
    "反复无常", "反躬自问", "返老还童", "方兴未艾", "防患未然",
    "防微杜渐", "放荡不羁", "飞黄腾达", "非同小可", "废寝忘食",
    "分崩离析", "分道扬镳", "奋不顾身", "愤愤不平", "丰富多彩",
    "丰功伟绩", "风调雨顺", "风和日丽", "风花雪月", "风平浪静",
    "风起云涌", "风雨同舟", "风雨飘摇", "锋芒毕露", "凤毛麟角",
    "奉公守法", "敷衍了事", "扶老携幼", "扶摇直上", "浮光掠影",
    "俯首帖耳", "釜底抽薪", "负荆请罪", "负隅顽抗", "妇孺皆知",
    "附庸风雅", "富丽堂皇",

    # ---- G ----
    "改邪归正", "盖世无双", "甘拜下风", "甘居人后", "感恩戴德",
    "敢作敢当", "刚愎自用", "高瞻远瞩", "高谈阔论", "高朋满座",
    "高风亮节", "高山流水", "各持己见", "各得其所", "各抒己见",
    "各行其是", "各有千秋", "各执一词", "各种各样", "各自为政",
    "格格不入", "隔靴搔痒", "功亏一篑", "公而忘私", "公事公办",
    "公报私仇", "孤芳自赏", "孤军奋战", "孤掌难鸣", "孤注一掷",
    "古色古香", "骨瘦如柴", "故步自封", "故弄玄虚", "顾此失彼",
    "顾名思义", "顾全大局", "瓜熟蒂落", "挂一漏万", "拐弯抹角",
    "关门大吉", "官官相护", "冠冕堂皇", "光彩夺目", "光风霁月",
    "光天化日", "光明磊落", "光宗耀祖", "广开言路", "归心似箭",
    "诡计多端", "鬼斧神工", "鬼鬼祟祟", "贵人多忘", "滚瓜烂熟",

    # ---- H ----
    "海阔天空", "海纳百川", "害群之马", "含辛茹苦", "邯郸学步",
    "寒来暑往", "汗马功劳", "汗牛充栋", "悍然不顾", "行云流水",
    "毫发不爽", "好高骛远", "好逸恶劳", "浩浩荡荡", "浩如烟海",
    "合情合理", "和蔼可亲", "和风细雨", "和颜悦色", "鹤立鸡群",
    "黑白分明", "横冲直撞", "横七竖八", "哄堂大笑", "鸿鹄之志",
    "后来居上", "后顾之忧", "厚此薄彼", "厚积薄发", "厚颜无耻",
    "呼风唤雨", "呼朋引伴", "囫囵吞枣", "狐假虎威", "狐朋狗友",
    "胡思乱想", "胡言乱语", "虎背熊腰", "虎踞龙盘", "虎视眈眈",
    "虎头蛇尾", "互相推诿", "花好月圆", "花红柳绿", "花团锦簇",
    "花言巧语", "画饼充饥", "画龙点睛", "画蛇添足", "欢天喜地",
    "欢欣鼓舞", "焕然一新", "患得患失", "患难与共", "荒诞不经",
    "荒无人烟", "黄粱一梦", "恍然大悟", "挥金如土", "回味无穷",
    "回头是岸", "回味无穷", "毁于一旦", "昏昏欲睡", "浑水摸鱼",
    "魂飞魄散", "魂牵梦萦", "混为一谈", "豁然开朗",

    # ---- J ----
    "饥不择食", "机不可失", "鸡飞蛋打", "鸡毛蒜皮", "鸡犬不宁",
    "积少成多", "积德行善", "激浊扬清", "急中生智", "急功近利",
    "急如星火", "急流勇退", "疾恶如仇", "集思广益", "挤眉弄眼",
    "己所不欲", "既往不咎", "计日程功", "寄人篱下", "家常便饭",
    "家喻户晓", "嘉言懿行", "坚持不懈", "坚定不移", "坚如磐石",
    "坚贞不屈", "艰苦奋斗", "艰难险阻", "简明扼要", "见多识广",
    "见义勇为", "见异思迁", "剑拔弩张", "渐入佳境", "鉴往知来",
    "箭在弦上", "将计就计", "将心比心", "交头接耳", "娇生惯养",
    "骄兵必败", "骄阳似火", "脚踏实地", "叫苦连天", "皆大欢喜",
    "接二连三", "接踵而至", "揭竿而起", "街谈巷议", "节外生枝",
    "节衣缩食", "洁身自好", "捷足先登", "截然不同", "竭尽全力",
    "津津有味", "筋疲力尽", "襟怀坦白", "紧锣密鼓", "锦上添花",
    "锦绣前程", "尽善尽美", "近水楼台", "近在咫尺", "进退两难",
    "进退维谷", "泾渭分明", "惊弓之鸟", "惊涛骇浪", "惊天动地",
    "精益求精", "井井有条", "井底之蛙", "敬而远之", "静如处子",
    "迥然不同", "炯炯有神", "就地取材", "居高临下", "举棋不定",
    "举世闻名", "举一反三", "举足轻重", "聚精会神", "据理力争",
    "开诚布公", "开门见山", "开天辟地", "凯旋而归", "慷慨激昂",
    "苛捐杂税", "可歌可泣", "可圈可点", "刻舟求剑", "刻不容缓",
    "空前绝后", "口若悬河", "口是心非", "苦口婆心", "苦尽甘来",
    "快马加鞭", "脍炙人口", "宽宏大量", "狂风暴雨", "旷日持久",
    "岿然不动", "困兽犹斗",

    # ---- L ----
    "来龙去脉", "来日方长", "来势汹汹", "来者不善", "蓝田生玉",
    "滥竽充数", "狼狈为奸", "狼吞虎咽", "劳苦功高", "劳民伤财",
    "老当益壮", "老马识途", "老谋深算", "老牛舐犊", "老气横秋",
    "乐不思蜀", "乐此不疲", "乐极生悲", "雷厉风行", "冷嘲热讽",
    "离乡背井", "礼尚往来", "礼贤下士", "理屈词穷", "理所当然",
    "理直气壮", "力不从心", "力挽狂澜", "历历在目", "立竿见影",
    "励精图治", "利令智昏", "连篇累牍", "恋恋不舍", "良辰美景",
    "两全其美", "量力而行", "寥若晨星", "寥寥无几", "了如指掌",
    "料事如神", "列鼎而食", "林林总总", "临危不惧", "临阵脱逃",
    "琳琅满目", "鳞次栉比", "伶牙俐齿", "另眼相看", "令人发指",
    "流芳百世", "流离失所", "流连忘返", "流水不腐", "流言蜚语",
    "龙飞凤舞", "龙马精神", "龙蛇混杂", "龙腾虎跃", "龙争虎斗",
    "漏网之鱼", "炉火纯青", "碌碌无为", "路不拾遗", "路见不平",
    "屡见不鲜", "乱七八糟", "乱作一团", "掠人之美", "略胜一筹",
    "论功行赏", "落花流水", "落落大方", "落魄不羁",

    # ---- M ----
    "麻木不仁", "马到成功", "马革裹尸", "马马虎虎", "埋头苦干",
    "满城风雨", "满腹经纶", "满载而归", "漫不经心", "漫山遍野",
    "忙里偷闲", "盲人摸象", "猫哭耗子", "毛遂自荐", "冒名顶替",
    "眉飞色舞", "眉开眼笑", "眉清目秀", "每况愈下", "美不胜收",
    "美中不足", "门可罗雀", "门庭若市", "蒙混过关", "梦寐以求",
    "弥天大谎", "迷途知返", "绵里藏针", "面不改色", "面红耳赤",
    "面面相觑", "面目全非", "面目一新", "妙不可言", "妙手回春",
    "民不聊生", "民富国强", "敏而好学", "名不副实", "名不虚传",
    "名垂青史", "名副其实", "名落孙山", "明辨是非", "明察暗访",
    "明察秋毫", "明目张胆", "明知故犯", "明争暗斗", "明哲保身",
    "摸不着头", "模棱两可", "摩肩接踵", "莫明其妙", "莫逆之交",
    "莫衷一是", "墨守成规", "默默无闻", "目不识丁", "目不转睛",
    "目瞪口呆", "目空一切", "目中无人",

    # ---- N ----
    "拿手好戏", "耐人寻味", "南辕北辙", "南柯一梦", "难分难解",
    "难能可贵", "难兄难弟", "恼羞成怒", "内忧外患", "能屈能伸",
    "能说会道", "泥牛入海", "泥沙俱下", "你死我活", "逆水行舟",
    "拈轻怕重", "年富力强", "念念不忘", "鸟语花香", "宁死不屈",
    "牛刀小试", "扭转乾坤", "浓妆艳抹", "弄巧成拙", "怒发冲冠",
    "怒形于色",

    # ---- P ----
    "拍案叫绝", "排山倒海", "攀龙附凤", "盘根错节", "判若两人",
    "庞然大物", "旁若无人", "旁征博引", "抛砖引玉", "跑马观花",
    "赔了夫人", "蓬荜生辉", "鹏程万里", "披荆斩棘", "披星戴月",
    "劈头盖脸", "皮开肉绽", "疲于奔命", "蚍蜉撼树", "片甲不留",
    "片言只字", "飘飘欲仙", "拼死拼活", "贫病交加", "品头论足",
    "平白无故", "平步青云", "平分秋色", "平起平坐", "平心静气",
    "平易近人", "评头品足", "凭空捏造", "迫不及待", "迫不得已",
    "破釜沉舟", "破镜重圆", "破涕为笑", "破绽百出", "扑朔迷离",
    "铺天盖地", "普天同庆",

    # ---- Q ----
    "七零八落", "七拼八凑", "其貌不扬", "奇花异草", "奇货可居",
    "奇谈怪论", "歧路亡羊", "骑虎难下", "旗开得胜", "岂有此理",
    "弃暗投明", "千变万化", "千差万别", "千锤百炼", "千方百计",
    "千军万马", "千钧一发", "千里迢迢", "千篇一律", "千奇百怪",
    "千山万水", "千丝万缕", "千头万绪", "千辛万苦", "千言万语",
    "千载难逢", "千真万确", "前车之鉴", "前赴后继", "前功尽弃",
    "前因后果", "潜移默化", "黔驴技穷", "浅尝辄止", "枪林弹雨",
    "强词夺理", "强弩之末", "强人所难", "巧夺天工", "巧立名目",
    "巧言令色", "切磋琢磨", "锲而不舍", "亲密无间", "亲如手足",
    "秦晋之好", "琴瑟和鸣", "勤能补拙", "勤学好问", "青出于蓝",
    "青红皂白", "青梅竹马", "青云直上", "轻车熟路", "轻而易举",
    "轻描淡写", "轻手轻脚", "倾家荡产", "倾盆大雨", "清规戒律",
    "情不自禁", "情同手足", "情有可原", "请君入瓮", "庆父不死",
    "穷兵黩武", "穷困潦倒", "穷途末路", "穷乡僻壤", "穷凶极恶",
    "秋高气爽", "求同存异", "求之不得", "曲高和寡", "曲径通幽",
    "取长补短", "取而代之", "取之不尽", "全力以赴", "全神贯注",
    "全心全意", "权衡利弊", "犬牙交错", "恰到好处", "恰到好处",
    "雀跃欢呼", "群策群力", "群龙无首", "群魔乱舞",

    # ---- R ----
    "然然可可", "饶有兴趣", "惹是生非", "热火朝天", "热泪盈眶",
    "人山人海", "人云亦云", "仁至义尽", "忍俊不禁", "忍气吞声",
    "忍辱负重", "任劳任怨", "任重道远", "日积月累", "日久天长",
    "日新月异", "日理万机", "日以继夜", "荣华富贵", "容光焕发",
    "融会贯通", "如虎添翼", "如花似锦", "如获至宝", "如火如荼",
    "如饥似渴", "如胶似漆", "如雷贯耳", "如梦初醒", "如释重负",
    "如鱼得水", "如影随形", "如意算盘", "乳臭未干", "入木三分",
    "入乡随俗", "软弱无能", "若明若暗", "若无其事",

    # ---- S ----
    "塞翁失马", "三令五申", "三言两语", "散兵游勇", "丧家之犬",
    "丧心病狂", "搔首弄姿", "杀鸡儆猴", "杀鸡取卵", "山崩地裂",
    "山高水长", "山高水低", "山清水秀", "山穷水尽", "山雨欲来",
    "闪烁其词", "善始善终", "伤风败俗", "上窜下跳", "上行下效",
    "尚方宝剑", "稍纵即逝", "少不更事", "舍本逐末", "舍己为人",
    "舍生取义", "舍生忘死", "设身处地", "身不由己", "身经百战",
    "身临其境", "身体力行", "身先士卒", "深更半夜", "深谋远虑",
    "深思熟虑", "神采奕奕", "神出鬼没", "神乎其神", "神机妙算",
    "神气活现", "神通广大", "审时度势", "生不逢时", "生灵涂炭",
    "生龙活虎", "生气勃勃", "生死攸关", "生离死别", "声东击西",
    "声色俱厉", "声嘶力竭", "声势浩大", "绳锯木断", "胜任愉快",
    "盛气凌人", "失之交臂", "诗情画意", "十恶不赦", "十拿九稳",
    "十全十美", "十万火急", "石破天惊", "时不我待", "时来运转",
    "拾金不昧", "食不甘味", "始终如一", "世外桃源", "事半功倍",
    "事过境迁", "事在人为", "视而不见", "视死如归", "适得其反",
    "适可而止", "手不释卷", "手忙脚乱", "手足无措", "守口如瓶",
    "守株待兔", "首屈一指", "寿比南山", "受宠若惊", "疏而不漏",
    "殊途同归", "熟能生巧", "熟视无睹", "鼠目寸光", "束手待毙",
    "束手无策", "束之高阁", "数不胜数", "数一数二", "双管齐下",
    "水到渠成", "水滴石穿", "水落石出", "水深火热", "水涨船高",
    "顺水推舟", "说三道四", "说一不二", "说长道短", "说一不二",
    "司空见惯", "思前想后", "斯斯文文", "死不瞑目", "死得其所",
    "死灰复燃", "死里逃生", "死气沉沉", "四分五裂", "四面楚歌",
    "四平八稳", "似是而非", "肆无忌惮", "松柏之志", "耸人听闻",
    "俗不可耐", "夙兴夜寐", "随波逐流", "随机应变", "随声附和",
    "随心所欲", "随遇而安", "岁月如梭", "损人利己", "所向披靡",
    "索然无味",

    # ---- T ----
    "他山之石", "太平盛世", "贪得无厌", "贪生怕死", "谈笑风生",
    "谈天说地", "弹尽粮绝", "叹为观止", "堂堂正正", "糖衣炮弹",
    "滔滔不绝", "逃之夭夭", "特立独行", "腾云驾雾", "啼饥号寒",
    "特立独行", "腾云驾雾", "啼饥号寒", "提心吊胆", "醍醐灌顶",
    "体无完肤", "天崩地坼", "天长地久", "天翻地覆", "天花乱坠",
    "天经地义", "天罗地网", "天南地北", "天怒人怨", "天衣无缝",
    "天涯海角", "天造地设", "天诛地灭", "甜言蜜语", "挑拨离间",
    "条分缕析", "铁面无私", "铁石心肠", "听天由命", "亭亭玉立",
    "挺身而出", "通情达理", "通宵达旦", "同仇敌忾", "同床异梦",
    "同甘共苦", "同流合污", "同舟共济", "痛不欲生", "痛改前非",
    "痛心疾首", "偷梁换柱", "头头是道", "头重脚轻", "投笔从戎",
    "投机取巧", "投其所好", "突飞猛进", "突然袭击", "图文并茂",
    "徒劳无功", "土崩瓦解", "吐故纳新", "推陈出新", "推心置腹",
    "退避三舍", "吞云吐雾", "脱口而出", "脱颖而出",

    # ---- W ----
    "挖空心思", "歪打正着", "外强中干", "完璧归赵", "玩忽职守",
    "万古长青", "万箭攒心", "万籁俱寂", "万马奔腾", "万念俱灰",
    "万事大吉", "万死不辞", "万无一失", "万象更新", "万众一心",
    "万紫千红", "亡羊补牢", "王侯将相", "网开一面", "忘恩负义",
    "忘乎所以", "望尘莫及", "望而生畏", "望梅止渴", "望眼欲穿",
    "危如累卵", "危言耸听", "危在旦夕", "微不足道", "为非作歹",
    "为虎作伥", "为所欲为", "惟妙惟肖", "唯利是图", "唯命是从",
    "维妙维肖", "尾大不掉", "尾生之信", "委曲求全", "娓娓动听",
    "未雨绸缪", "味同嚼蜡", "畏首畏尾", "温故知新", "温文尔雅",
    "闻风丧胆", "闻鸡起舞", "闻所未闻", "稳操胜券", "稳如泰山",
    "问心无愧", "瓮中捉鳖", "我行我素", "卧薪尝胆", "乌合之众",
    "乌烟瘴气", "无中生有", "无病呻吟", "无地自容", "无的放矢",
    "无恶不作", "无法无天", "无价之宝", "无精打采", "无可奈何",
    "无孔不入", "无理取闹", "无穷无尽", "无人问津", "无伤大雅",
    "无所事事", "无所适从", "无所畏惧", "无所作为", "无微不至",
    "无懈可击", "无言以对", "无依无靠", "无影无踪", "无忧无虑",
    "无与伦比", "无缘无故", "五彩缤纷", "五光十色", "五湖四海",
    "五花八门", "五体投地", "五颜六色", "勿谓言之", "物极必反",
    "物尽其用", "物美价廉", "物是人非",

    # ---- X ----
    "息息相关", "惜墨如金", "稀奇古怪", "熙熙攘攘", "嘻皮笑脸",
    "嬉笑怒骂", "习以为常", "喜出望外", "喜形于色", "喜笑颜开",
    "喜新厌旧", "戏如人生", "细致入微", "瑕不掩瑜", "瑕瑜互见",
    "下不为例", "先发制人", "先礼后兵", "先入为主", "先声夺人",
    "先斩后奏", "鲜为人知", "显而易见", "险象环生", "相得益彰",
    "相辅相成", "相敬如宾", "相提并论", "相形见绌", "相依为命",
    "香消玉殒", "想方设法", "想入非非", "响彻云霄", "想当然耳",
    "逍遥法外", "销声匿迹", "小巧玲珑", "小题大做", "小心翼翼",
    "小恩小惠", "晓以大义", "笑逐颜开", "邪不压正", "挟天子令",
    "心安理得", "心潮澎湃", "心驰神往", "心胆俱裂", "心烦意乱",
    "心服口服", "心腹之患", "心甘情愿", "心花怒放", "心怀叵测",
    "心慌意乱", "心灰意冷", "心急如焚", "心坚石穿", "心惊胆战",
    "心旷神怡", "心领神会", "心满意足", "心明眼亮", "心平气和",
    "心神不宁", "心事重重", "心术不正", "心心相印", "心血来潮",
    "心猿意马", "心悦诚服", "心照不宣", "心直口快", "欣欣向荣",
    "新陈代谢", "信口开河", "信誓旦旦", "信以为真", "兴风作浪",
    "兴高采烈", "兴师动众", "星罗棋布", "惺惺作态", "形单影只",
    "形影不离", "形影相吊", "兴利除弊", "幸灾乐祸", "凶神恶煞",
    "胸有成竹", "雄心壮志", "朽木不雕", "秀外慧中", "秀色可餐",
    "袖手旁观", "栩栩如生", "虚怀若谷", "虚情假意", "虚无缥缈",
    "虚张声势", "栩栩如生", "絮絮叨叨", "轩然大波", "喧宾夺主",
    "悬崖勒马", "学以致用", "学而不厌", "学富五车", "雪中送炭",
    "血肉相连", "寻根究底", "循序渐进",

    # ---- Y ----
    "鸦雀无声", "睚眦必报", "哑口无言", "雅俗共赏", "烟消云散",
    "延年益寿", "严阵以待", "言简意赅", "言听计从", "言外之意",
    "言下之意", "言犹在耳", "言之有理", "岩穴之士", "颜面扫地",
    "奄奄一息", "眼花缭乱", "眼明手快", "扬长避短", "扬眉吐气",
    "阳奉阴违", "洋洋得意", "洋洋大观", "仰人鼻息", "养虎为患",
    "养精蓄锐", "怏怏不乐", "样样俱全", "妖言惑众", "遥相呼应",
    "摇摇欲坠", "摇旗呐喊", "咬文嚼字", "咬牙切齿", "要言不烦",
    "叶公好龙", "夜长梦多", "夜以继日", "一败涂地", "一败如水",
    "一本正经", "一臂之力", "一表人才", "一尘不染", "一成不变",
    "一筹莫展", "一触即发", "一刀两断", "一发千钧", "一帆风顺",
    "一反常态", "一鼓作气", "一哄而散", "一呼百应", "一挥而就",
    "一见如故", "一箭双雕", "一举两得", "一决雌雄", "一蹶不振",
    "一刻千金", "一孔之见", "一来二去", "一览无余", "一劳永逸",
    "一鳞半爪", "一落千丈", "一马当先", "一脉相承", "一毛不拔",
    "一面之词", "一鸣惊人", "一命呜呼", "一模一样", "一目了然",
    "一念之差", "一诺千金", "一贫如洗", "一气呵成", "一窍不通",
    "一窍不通", "一身正气", "一生一世", "一视同仁", "一世之雄",
    "一手遮天", "一丝不苟", "一塌糊涂", "一团和气", "一网打尽",
    "一望无际", "一无所有", "一无是处", "一席之地", "一泻千里",
    "一心一意", "一言九鼎", "一言难尽", "一叶知秋", "一意孤行",
    "一应俱全", "一拥而上", "一朝一夕", "一针见血", "一知半解",
    "一掷千金", "一字千金", "一字之师", "怡然自得", "贻笑大方",
    "移花接木", "移山倒海", "遗臭万年", "遗风余烈", "疑神疑鬼",
    "以卵击石", "以貌取人", "以身殉职", "以身作则", "以退为进",
    "以一当十", "义不容辞", "义薄云天", "义愤填膺", "义无反顾",
    "异口同声", "异曲同工", "异想天开", "意在言外", "因材施教",
    "因地制宜", "因陋就简", "因势利导", "因果报应", "因小失大",
    "阴谋诡计", "殷勤备至", "引经据典", "引狼入室", "引人入胜",
    "引人注目", "引以为戒", "饮鸩止渴", "隐姓埋名", "英雄辈出",
    "英姿飒爽", "鹦鹉学舌", "迎刃而解", "营私舞弊", "蝇头小利",
    "应付自如", "应接不暇", "映入眼帘", "庸人自扰", "永垂不朽",
    "勇往直前", "优柔寡断", "忧国忧民", "忧心忡忡", "幽明异路",
    "悠然自得", "犹豫不决", "油腔滑调", "油头粉面", "游刃有余",
    "有备无患", "有口皆碑", "有口难言", "有名无实", "有声有色",
    "有始有终", "有条不紊", "有血有肉", "有志竟成", "有目共睹",
    "诱敌深入", "囿于成见", "迂回曲折", "余音绕梁", "鱼目混珠",
    "愚公移山", "与日俱增", "与世长辞", "与时俱进", "羽毛未丰",
    "雨后春笋", "语重心长", "玉树临风", "玉石俱焚", "浴血奋战",
    "欲罢不能", "欲擒故纵", "欲速不达", "寓教于乐", "寓庄于谐",
    "源远流长", "远走高飞", "怨天尤人", "约定俗成", "月白风清",
    "月明星稀", "悦耳动听", "越俎代庖", "云开见日", "云消雾散",
    "运筹帷幄", "运用自如",

    # ---- Z ----
    "杂乱无章", "再接再厉", "在所不辞", "在所难免", "载歌载舞",
    "赞不绝口", "早出晚归", "造谣惑众", "责无旁贷", "择善而从",
    "贼喊捉贼", "瞻前顾后", "斩草除根", "斩钉截铁", "战无不胜",
    "张灯结彩", "张冠李戴", "张口结舌", "张牙舞爪", "仗义执言",
    "招兵买马", "招摇过市", "招摇撞骗", "朝三暮四", "朝气蓬勃",
    "照本宣科", "遮天蔽日", "折戟沉沙", "真心诚意", "真知灼见",
    "针锋相对", "珍禽异兽", "枕戈待旦", "振臂一呼", "振奋人心",
    "振振有词", "争分夺秒", "争奇斗艳", "争先恐后", "铮铮铁骨",
    "蒸蒸日上", "整装待发", "正本清源", "正大光明", "正襟危坐",
    "正人君子", "正言厉色", "正中下怀", "郑重其事", "政通人和",
    "之乎者也", "支离破碎", "知己知彼", "知法犯法", "知难而退",
    "知书达理", "知无不言", "执迷不悟", "直截了当", "直言不讳",
    "只言片语", "纸醉金迷", "指鹿为马", "指日可待", "指手画脚",
    "志同道合", "志在四方", "炙手可热", "治国安邦", "炙手可热",
    "智勇双全", "中流砥柱", "忠心耿耿", "忠言逆耳", "终南捷径",
    "众口铄金", "众目睽睽", "众矢之的", "众望所归", "众志成城",
    "重见天日", "重蹈覆辙", "重温旧梦", "重振旗鼓", "周而复始",
    "珠联璧合", "珠围翠绕", "竹报平安", "逐鹿中原", "煮豆燃萁",
    "助人为乐", "筑室道谋", "专心致志", "转败为胜", "转危为安",
    "装模作样", "壮志凌云", "追本溯源", "惴惴不安", "谆谆教导",
    "卓尔不群", "着手成春", "捉襟见肘", "孜孜不倦", "子虚乌有",
    "自暴自弃", "自不量力", "自惭形秽", "自成一家", "自吹自擂",
    "自高自大", "自给自足", "自愧不如", "自欺欺人", "自强不息",
    "自生自灭", "自食其果", "自食其力", "自始至终", "自私自利",
    "自投罗网", "自相矛盾", "自言自语", "自由自在", "自怨自艾",
    "走马观花", "走投无路", "足智多谋", "钻牛角尖", "醉生梦死",
    "尊师重道", "左右逢源", "左右开弓", "坐井观天", "坐立不安",
    "坐视不救", "坐收渔利", "坐以待毙", "作壁上观", "作恶多端",
    "作奸犯科", "作威作福",
]

# 去重并排序
CHENGYU_SET = sorted(set(CHENGYU_DATA))

# ==================== 拼音工具 ====================
def get_last_pinyin(chengyu):
    """获取成语最后一个字的拼音（不带声调）"""
    try:
        py = pinyin(chengyu[-1], style=Style.TONE3)[0][0]
        return py.lower().rstrip('0123456789')
    except:
        return ""

def get_first_pinyin(chengyu):
    """获取成语第一个字的拼音（不带声调）"""
    try:
        py = pinyin(chengyu[0], style=Style.TONE3)[0][0]
        return py.lower().rstrip('0123456789')
    except:
        return ""

def get_pinyin_full(chengyu):
    """获取整个成语的拼音标注"""
    try:
        pys = pinyin(chengyu, style=Style.TONE3)
        return [p[0].lower() for p in pys]
    except:
        return ["?"] * len(chengyu)

# 构建 尾字拼音 -> [成语列表] 映射
CHENGYU_DICT = {}
for cy in CHENGYU_SET:
    lp = get_last_pinyin(cy)
    if lp:
        CHENGYU_DICT.setdefault(lp, []).append(cy)

# ==================== UI 组件 ====================
class Button:
    """圆角按钮"""
    def __init__(self, x, y, w, h, text, font_size=26, 
                 color=BTN_PRIMARY, hover_color=BTN_HOVER, 
                 text_color=TEXT_COLOR, icon=""):
        self.rect = pygame.Rect(x, y, w, h)
        self.text = text
        self.icon = icon
        self.font = get_font(font_size)
        self.color = color
        self.hover_color = hover_color
        self.text_color = text_color
        self.is_hovered = False
        self.is_pressed = False
        self.press_offset = 0

    def update(self, mouse_pos, mouse_pressed):
        was_hovered = self.is_hovered
        self.is_hovered = self.rect.collidepoint(mouse_pos)
        self.is_pressed = self.is_hovered and mouse_pressed
        self.press_offset = 2 if self.is_pressed else 0

    def draw(self, surface):
        color = self.hover_color if self.is_hovered else self.color
        if self.is_pressed:
            color = tuple(max(0, c - 30) for c in self.color)
        
        rect = self.rect.move(0, self.press_offset)
        # 阴影
        shadow = rect.move(0, 3)
        pygame.draw.rect(surface, (15, 18, 30), shadow, border_radius=12)
        # 按钮主体
        pygame.draw.rect(surface, color, rect, border_radius=12)
        # 高光边框
        border_c = tuple(min(255, c + 40) for c in color)
        pygame.draw.rect(surface, border_c, rect, width=2, border_radius=12)
        
        display = f"{self.icon} {self.text}" if self.icon else self.text
        text_surf = self.font.render(display, True, self.text_color)
        text_rect = text_surf.get_rect(center=(rect.centerx, rect.centery + self.press_offset))
        surface.blit(text_surf, text_rect)

    def is_clicked(self, mouse_pos, just_pressed):
        return self.rect.collidepoint(mouse_pos) and just_pressed


class InputBox:
    """输入框"""
    def __init__(self, x, y, w, h, font_size=34, placeholder="输入成语..."):
        self.rect = pygame.Rect(x, y, w, h)
        self.text = ""
        self.placeholder = placeholder
        self.font = get_font(font_size)
        self.active = False
        self.cursor_visible = True
        self.cursor_timer = 0
        self.max_len = 8
        self.shake_timer = 0

    def handle_event(self, event):
        if event.type == pygame.MOUSEBUTTONDOWN:
            self.active = self.rect.collidepoint(event.pos)
        if event.type == pygame.KEYDOWN and self.active:
            if event.key == pygame.K_RETURN:
                return "submit"
            elif event.key == pygame.K_BACKSPACE:
                self.text = self.text[:-1]
            elif len(self.text) < self.max_len and event.unicode.isprintable():
                self.text += event.unicode
        return None

    def update(self, dt):
        self.cursor_timer += dt
        if self.cursor_timer >= 500:
            self.cursor_visible = not self.cursor_visible
            self.cursor_timer = 0
        if self.shake_timer > 0:
            self.shake_timer -= dt

    def shake(self):
        self.shake_timer = 300

    def draw(self, surface):
        shake_x = random.randint(-3, 3) if self.shake_timer > 0 else 0
        
        bg = INPUT_BG if not self.active else (52, 65, 100)
        rect = self.rect.move(shake_x, 0)
        
        # 阴影
        shadow = rect.move(0, 3)
        pygame.draw.rect(surface, (15, 18, 30), shadow, border_radius=12)
        # 背景
        pygame.draw.rect(surface, bg, rect, border_radius=12)
        # 边框
        bc = ACCENT_GOLD if self.active else (80, 95, 130)
        pygame.draw.rect(surface, bc, rect, width=2, border_radius=12)

        if self.text:
            text_surf = self.font.render(self.text, True, TEXT_COLOR)
            surface.blit(text_surf, (rect.x + 18, rect.centery - text_surf.get_height() // 2))
            if self.active and self.cursor_visible:
                cx = rect.x + 18 + text_surf.get_width() + 3
                pygame.draw.line(surface, TEXT_COLOR, (cx, rect.y + 12), (cx, rect.y + rect.h - 12), 2)
        else:
            ph_surf = self.font.render(self.placeholder, True, (100, 110, 140))
            surface.blit(ph_surf, (rect.x + 18, rect.centery - ph_surf.get_height() // 2))

    def clear(self):
        self.text = ""


class Particle:
    """粒子特效"""
    def __init__(self, x, y, color, speed=2, size=None):
        self.x = x
        self.y = y
        self.color = color
        angle = random.uniform(0, math.pi * 2)
        spd = speed * random.uniform(0.5, 2.5)
        self.vx = math.cos(angle) * spd
        self.vy = math.sin(angle) * spd
        self.vy -= random.uniform(0.5, 1.5)  # 向上偏移
        self.life = random.randint(40, 80)
        self.max_life = self.life
        self.size = size or random.randint(3, 7)
        self.gravity = 0.08

    def update(self):
        self.x += self.vx
        self.y += self.vy
        self.vy += self.gravity
        self.life -= 1
        self.size = max(0.5, self.size - 0.08)

    def draw(self, surface):
        alpha = int(255 * (self.life / self.max_life))
        s = pygame.Surface((int(self.size*2)+2, int(self.size*2)+2), pygame.SRCALPHA)
        color = (*self.color, alpha)
        pygame.draw.circle(s, color, (s.get_width()//2, s.get_height()//2), int(self.size))
        surface.blit(s, (int(self.x - self.size - 1), int(self.y - self.size - 1)))


class FloatingText:
    """飘浮文字特效"""
    def __init__(self, x, y, text, color, font_size=24, duration=60):
        self.x = x
        self.y = y
        self.text = text
        self.color = color
        self.font = get_font(font_size, bold=True)
        self.life = duration
        self.max_life = duration
        self.vy = -1.5

    def update(self):
        self.y += self.vy
        self.life -= 1

    def draw(self, surface):
        alpha = int(255 * (self.life / self.max_life))
        s = self.font.render(self.text, True, self.color)
        surf = pygame.Surface(s.get_size(), pygame.SRCALPHA)
        surf.blit(s, (0, 0))
        surf.set_alpha(alpha)
        rect = surf.get_rect(center=(self.x, self.y))
        surface.blit(surf, rect)


# ==================== 主游戏类 ====================
class ChengyuGame:
    def __init__(self):
        self.screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
        pygame.display.set_caption("成语接龙 · Pygame 精美版")
        self.clock = pygame.time.Clock()
        self.running = True

        # 游戏状态
        self.state = "menu"  # menu, playing, game_over, victory
        self.chain = []
        self.used_set = set()
        self.score = 0
        self.combo = 0
        self.max_combo = 0
        self.total_rounds = 0
        self.message = ""
        self.message_color = TEXT_COLOR
        self.message_timer = 0

        # 特效
        self.particles = []
        self.floating_texts = []
        self.anim_offset = 0
        self.new_cy_anim = 0
        self.bg_particles = []

        # 初始化背景粒子
        for _ in range(30):
            self.bg_particles.append({
                'x': random.randint(0, SCREEN_WIDTH),
                'y': random.randint(0, SCREEN_HEIGHT),
                'size': random.randint(1, 3),
                'speed': random.uniform(0.2, 0.8),
                'alpha': random.randint(20, 60)
            })

        # UI
        input_y = SCREEN_HEIGHT - 130
        self.input_box = InputBox(SCREEN_WIDTH // 2 - 220, input_y, 380, 52, 34, "输入4字成语后按回车 ↵")
        self.submit_btn = Button(SCREEN_WIDTH // 2 + 180, input_y, 110, 52, "接龙", 26, BTN_PRIMARY, BTN_HOVER, icon="✓")
        self.hint_btn = Button(SCREEN_WIDTH // 2 - 80, input_y + 65, 95, 38, "提示", 20, BTN_SUCCESS, BTN_SUCCESS_H, icon="💡")
        self.restart_btn = Button(SCREEN_WIDTH // 2 + 30, input_y + 65, 95, 38, "重开", 20, BTN_WARNING, BTN_WARNING_H, icon="🔄")
        self.quit_btn = Button(SCREEN_WIDTH // 2 + 140, input_y + 65, 95, 38, "退出", 20, BTN_DANGER, BTN_DANGER_H, icon="✕")

        # 菜单按钮
        self.start_btn = Button(SCREEN_WIDTH // 2 - 120, SCREEN_HEIGHT // 2 + 60, 240, 60, "开始游戏", 30, BTN_PRIMARY, BTN_HOVER, icon="▶")
        self.help_btn = Button(SCREEN_WIDTH // 2 - 120, SCREEN_HEIGHT // 2 + 140, 240, 45, "游戏说明", 22, (80, 80, 120), (100, 100, 150), icon="?")

        self.start_game()

    # ==================== 游戏逻辑 ====================
    def start_game(self):
        self.chain = []
        self.used_set = set()
        self.score = 0
        self.combo = 0
        self.max_combo = 0
        self.total_rounds = 0
        self.message = "🎮 游戏开始！电脑先出一个成语"
        self.message_color = ACCENT_GOLD
        self.message_timer = 180
        self.particles = []
        self.floating_texts = []
        self.state = "playing"
        self.input_box.clear()
        self.input_box.active = True

        # 电脑先出
        first = random.choice(CHENGYU_SET)
        self.chain.append(first)
        self.used_set.add(first)
        self.new_cy_anim = 40
        self.spawn_chengyu_particles(first, is_player=False)

    def spawn_particles(self, x, y, color, count=25, speed=3):
        for _ in range(count):
            self.particles.append(Particle(x, y, color, speed=speed))

    def spawn_chengyu_particles(self, chengyu, is_player=True):
        """在接龙链区域为成语生成粒子"""
        color = ACCENT_GOLD if is_player else CHAIN_TAG_PC
        cx = SCREEN_WIDTH // 2 + random.randint(-100, 100)
        cy = SCREEN_HEIGHT // 2 - 50 + random.randint(-30, 30)
        self.spawn_particles(cx, cy, color, count=20, speed=2.5)

    def add_floating_text(self, x, y, text, color, font_size=24):
        self.floating_texts.append(FloatingText(x, y, text, color, font_size))

    def show_message(self, text, color=TEXT_COLOR, duration=150):
        self.message = text
        self.message_color = color
        self.message_timer = duration

    def check_player_input(self, text):
        text = text.strip()

        if len(text) != 4:
            self.show_message("❌ 请输入4字成语！", ACCENT_RED)
            self.combo = 0
            self.input_box.shake()
            self.spawn_particles(self.input_box.rect.centerx, self.input_box.rect.centery, ACCENT_RED, 10, 2)
            return

        if text not in CHENGYU_SET:
            self.show_message("❌ 不是有效成语或不在词库中！", ACCENT_RED)
            self.combo = 0
            self.input_box.shake()
            self.spawn_particles(self.input_box.rect.centerx, self.input_box.rect.centery, ACCENT_RED, 10, 2)
            return

        if text in self.used_set:
            self.show_message("❌ 这个成语已经用过了！", ACCENT_RED)
            self.combo = 0
            self.input_box.shake()
            return

        # 检查接龙规则
        last_cy = self.chain[-1]
        required_py = get_last_pinyin(last_cy)
        input_first_py = get_first_pinyin(text)

        if required_py != input_first_py:
            self.show_message(f"❌ 首字拼音应为「{required_py}」，你输入的是「{input_first_py}」", ACCENT_RED)
            self.combo = 0
            self.input_box.shake()
            # 显示可接的候选数量
            cands = len([c for c in CHENGYU_DICT.get(required_py, []) if c not in self.used_set])
            if cands > 0:
                self.show_message(f"❌ 需要首字拼音「{required_py}」的成语（还有{cands}个可选）", ACCENT_RED, 200)
            return

        # ✅ 成功
        self.chain.append(text)
        self.used_set.add(text)
        self.combo += 1
        self.max_combo = max(self.max_combo, self.combo)
        self.total_rounds += 1

        base = 10
        combo_bonus = self.combo * 5
        total = base + combo_bonus
        self.score += total

        msg = f"✅ 接龙成功！+{total}分"
        if self.combo >= 3:
            msg += f" 🔥连击x{self.combo}!"
        self.show_message(msg, ACCENT_GREEN, 120)
        self.spawn_particles(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2 - 30, ACCENT_GREEN, 30, 3)
        self.add_floating_text(SCREEN_WIDTH // 2 + random.randint(-80, 80), 
                               SCREEN_HEIGHT // 2 - 80, f"+{total}", ACCENT_GOLD, 28)
        self.new_cy_anim = 35
        self.spawn_chengyu_particles(text, is_player=True)

        # 电脑接龙
        pygame.time.wait(500)  # 稍微停顿增加节奏感
        self.computer_turn()

    def computer_turn(self):
        last_cy = self.chain[-1]
        required_py = get_last_pinyin(last_cy)
        cands = [c for c in CHENGYU_DICT.get(required_py, []) if c not in self.used_set]

        if not cands:
            self.show_message(f"🎉 电脑接不上啦！你赢了！得分：{self.score}", ACCENT_GOLD, 300)
            self.state = "victory"
            self.spawn_particles(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2, ACCENT_GOLD, 60, 4)
            self.add_floating_text(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2 - 60, "VICTORY!", ACCENT_GOLD, 36)
            return

        next_cy = random.choice(cands)
        self.chain.append(next_cy)
        self.used_set.add(next_cy)
        self.total_rounds += 1
        self.show_message(f"💻 电脑接：{next_cy}", ACCENT_BLUE, 150)
        self.new_cy_anim = 35
        self.spawn_chengyu_particles(next_cy, is_player=False)

    def get_hint(self):
        if not self.chain or self.state != "playing":
            return
        last_cy = self.chain[-1]
        required_py = get_last_pinyin(last_cy)
        cands = [c for c in CHENGYU_DICT.get(required_py, []) if c not in self.used_set]
        if cands:
            hint = random.choice(cands)
            self.score = max(0, self.score - 5)
            self.show_message(f"💡 提示：试试「{hint}」(扣5分)", ACCENT_BLUE, 200)
        else:
            self.show_message("💡 没有可用的提示了！", TEXT_DIM, 120)

    # ==================== 绘制方法 ====================
    def draw_background(self):
        self.screen.fill(BG_COLOR)
        # 背景浮动粒子
        for bp in self.bg_particles:
            bp['y'] -= bp['speed']
            if bp['y'] < -10:
                bp['y'] = SCREEN_HEIGHT + 10
                bp['x'] = random.randint(0, SCREEN_WIDTH)
            s = pygame.Surface((bp['size']*2, bp['size']*2), pygame.SRCALPHA)
            pygame.draw.circle(s, (100, 130, 200, bp['alpha']), (bp['size'], bp['size']), bp['size'])
            self.screen.blit(s, (int(bp['x']-bp['size']), int(bp['y']-bp['size'])))

        # 装饰网格
        for i in range(0, SCREEN_WIDTH, 100):
            pygame.draw.line(self.screen, (30, 38, 60), (i, 0), (i, SCREEN_HEIGHT), 1)
        for j in range(0, SCREEN_HEIGHT, 100):
            pygame.draw.line(self.screen, (30, 38, 60), (0, j), (SCREEN_WIDTH, j), 1)

    def draw_title_bar(self):
        """顶部标题栏"""
        bar_rect = pygame.Rect(0, 0, SCREEN_WIDTH, 95)
        pygame.draw.rect(self.screen, (28, 34, 58), bar_rect)
        pygame.draw.line(self.screen, (50, 62, 100), (0, 95), (SCREEN_WIDTH, 95), 2)

        # 标题
        title_font = get_font(42, bold=True)
        title_surf = title_font.render("成 语 接 龙", True, ACCENT_GOLD)
        self.screen.blit(title_surf, (25, 18))

        # 副标题
        sub_font = get_font(15)
        sub_surf = sub_font.render("传承中华文化 · 挑战词汇极限", True, TEXT_DIM)
        self.screen.blit(sub_surf, (30, 68))

        # 右侧统计
        stats_font = get_font(16)
        stats = f"词库: {len(CHENGYU_SET)}个成语 | 拼音: {len(CHENGYU_DICT)}类"
        stats_surf = stats_font.render(stats, True, TEXT_DIM)
        self.screen.blit(stats_surf, (SCREEN_WIDTH - stats_surf.get_width() - 20, 35))

        tip = "规则: 下一成语首字拼音 = 上一成语尾字拼音"
        tip_surf = stats_font.render(tip, True, TEXT_DIM)
        self.screen.blit(tip_surf, (SCREEN_WIDTH - tip_surf.get_width() - 20, 58))

    def draw_score_panel(self):
        """左侧分数面板"""
        panel = pygame.Rect(15, 110, 210, 155)
        pygame.draw.rect(self.screen, PANEL_BG, panel, border_radius=14)
        pygame.draw.rect(self.screen, (55, 70, 110), panel, width=2, border_radius=14)

        font_label = get_font(15)
        font_val = get_font(36, bold=True)
        font_small = get_font(14)

        # 分数
        self.screen.blit(font_label.render("SCORE", True, TEXT_DIM), (30, 118))
        sc = font_val.render(str(self.score), True, ACCENT_GOLD)
        self.screen.blit(sc, (30, 138))

        # 连击
        self.screen.blit(font_label.render("COMBO", True, TEXT_DIM), (130, 118))
        combo_color = ACCENT_GREEN if self.combo >= 3 else TEXT_COLOR
        cb = font_val.render(f"x{self.combo}", True, combo_color)
        self.screen.blit(cb, (125, 138))

        # 分割线
        pygame.draw.line(self.screen, (55, 70, 110), (30, 188), (210, 188), 1)

        # 详细信息
        self.screen.blit(font_small.render(f"最长连击: x{self.max_combo}", True, TEXT_DIM), (30, 196))
        self.screen.blit(font_small.render(f"接龙长度: {len(self.chain)}", True, TEXT_DIM), (30, 216))
        self.screen.blit(font_small.render(f"已用成语: {len(self.used_set)}", True, TEXT_DIM), (130, 216))

    def draw_target_panel(self):
        """当前目标面板"""
        panel = pygame.Rect(SCREEN_WIDTH - 225, 110, 210, 100)
        pygame.draw.rect(self.screen, (45, 35, 65), panel, border_radius=14)
        pygame.draw.rect(self.screen, (100, 65, 130), panel, width=2, border_radius=14)

        font_label = get_font(14)
        font_char = get_font(48, bold=True)
        font_py = get_font(18)

        self.screen.blit(font_label.render("🎯 需要接的尾字", True, (190, 170, 210)), (panel.x + 15, panel.y + 8))

        if self.chain:
            last_char = self.chain[-1][-1]
            last_py = get_last_pinyin(self.chain[-1])
            char_surf = font_char.render(last_char, True, ACCENT_GOLD)
            self.screen.blit(char_surf, (panel.x + 20, panel.y + 28))
            py_surf = font_py.render(f"拼音: {last_py}", True, (210, 190, 230))
            self.screen.blit(py_surf, (panel.x + 80, panel.y + 45))
            tip = font_label.render("输入首字同音的成语", True, TEXT_DIM)
            self.screen.blit(tip, (panel.x + 15, panel.y + 75))

    def draw_chain_panel(self):
        """中间接龙链面板"""
        panel = pygame.Rect(240, 110, SCREEN_WIDTH - 480, SCREEN_HEIGHT - 275)
        pygame.draw.rect(self.screen, PANEL_BG, panel, border_radius=14)
        pygame.draw.rect(self.screen, (55, 70, 110), panel, width=2, border_radius=14)

        # 标题栏
        header_font = get_font(18, bold=True)
        h_surf = header_font.render("📜 接龙记录", True, (180, 190, 220))
        self.screen.blit(h_surf, (258, 118))
        
        count_surf = get_font(14).render(f"共{len(self.chain)}条", True, TEXT_DIM)
        self.screen.blit(count_surf, (panel.right - count_surf.get_width() - 20, 122))

        # 分割线
        pygame.draw.line(self.screen, (55, 70, 110), (258, 148), (panel.right - 10, 148), 2)

        if not self.chain:
            empty_font = get_font(20)
            s = empty_font.render("等待开始...", True, TEXT_DIM)
            self.screen.blit(s, (panel.centerx - s.get_width()//2, panel.centery))
            return

        # 滚动显示最近条目
        max_visible = 13
        start_idx = max(0, len(self.chain) - max_visible)
        visible = self.chain[start_idx:]
        item_h = 36
        y_start = 156

        for i, cy in enumerate(visible):
            y = y_start + i * item_h
            if y > panel.bottom - 15:
                break

            is_new = (i == len(visible) - 1)
            is_pc = ((start_idx + i) % 2 == 1)  # 电脑回合
            idx = start_idx + i

            # 行动画
            x_offset = 0
            alpha_offset = 0
            if is_new and self.new_cy_anim > 0:
                progress = 1 - (self.new_cy_anim / 35)
                x_offset = int(30 * (1 - progress))
                alpha_offset = int(60 * (1 - progress))

            # 行背景
            row_bg = (48, 58, 92) if is_pc else (42, 52, 84)
            row_rect = pygame.Rect(252, y - 2, panel.width - 30, item_h - 4)
            pygame.draw.rect(self.screen, row_bg, row_rect, border_radius=8)

            # 序号
            idx_font = get_font(13)
            idx_color = CHAIN_TAG_PC if is_pc else CHAIN_TAG_HUMAN
            idx_surf = idx_font.render(f"#{idx+1}", True, idx_color)
            self.screen.blit(idx_surf, (260 - x_offset, y + 6))

            # 成语
            cy_font = get_font(22, bold=True)
            cy_color = TEXT_COLOR
            if is_new and self.new_cy_anim > 0:
                if self.new_cy_anim % 8 < 4:
                    cy_color = ACCENT_GOLD
            cy_surf = cy_font.render(cy, True, cy_color)
            self.screen.blit(cy_surf, (310 - x_offset, y + 3))

            # 拼音标注
            try:
                pys = get_pinyin_full(cy)
                py_text = " ".join(pys)
                py_surf = get_font(12).render(py_text, True, (120, 135, 165))
                self.screen.blit(py_surf, (310 - x_offset, y + 20))
            except:
                pass

            # 角色标记
            tag = "🤖" if is_pc else "🧑"
            tag_surf = get_font(15).render(tag, True, (160, 170, 195))
            self.screen.blit(tag_surf, (panel.right - 45, y + 5))

            # 连接箭头
            if i < len(visible) - 1:
                arrow_font = get_font(12)
                arrow_surf = arrow_font.render("↓", True, (80, 95, 130))
                self.screen.blit(arrow_surf, (panel.centerx - 4, y + item_h - 2))

        # 省略提示
        if start_idx > 0:
            more_font = get_font(13)
            more_surf = more_font.render(f"...前面还有{start_idx}个", True, TEXT_DIM)
            self.screen.blit(more_surf, (258, 152))

    def draw_input_area(self):
        """底部输入区域背景"""
        area_rect = pygame.Rect(0, SCREEN_HEIGHT - 165, SCREEN_WIDTH, 165)
        pygame.draw.rect(self.screen, (28, 34, 58), area_rect)
        pygame.draw.line(self.screen, (50, 62, 100), (0, SCREEN_HEIGHT - 165), (SCREEN_WIDTH, SCREEN_HEIGHT - 165), 2)

    def draw_message(self):
        """消息提示"""
        if self.message_timer > 0 and self.message:
            alpha = min(255, self.message_timer * 4)
            font = get_font(20)
            msg_surf = font.render(self.message, True, self.message_color)
            msg_rect = msg_surf.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT - 190))

            bg = pygame.Surface((msg_rect.width + 40, msg_rect.height + 14), pygame.SRCALPHA)
            pygame.draw.rect(bg, (20, 25, 45, min(220, alpha)), bg.get_rect(), border_radius=10)
            self.screen.blit(bg, (msg_rect.x - 20, msg_rect.y - 7))
            self.screen.blit(msg_surf, msg_rect)

    def draw_game_overlay(self):
        """游戏结束/胜利覆盖层"""
        overlay = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT), pygame.SRCALPHA)
        overlay.fill((0, 0, 0, 170))
        self.screen.blit(overlay, (0, 0))

        if self.state == "victory":
            title = "🎉 你赢了！电脑接不上啦！🎉"
            color = ACCENT_GOLD
            subtitle = "恭喜你战胜了电脑！"
        else:
            title = "💀 游戏结束 💀"
            color = ACCENT_RED
            subtitle = "再接再厉！"

        big_font = get_font(48, bold=True)
        title_surf = big_font.render(title, True, color)
        rect = title_surf.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2 - 100))
        self.screen.blit(title_surf, rect)

        sub_font = get_font(24)
        sub_surf = sub_font.render(subtitle, True, TEXT_COLOR)
        self.screen.blit(sub_surf, sub_surf.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2 - 45)))

        # 数据卡片
        card_font = get_font(22)
        cards = [
            f"最终得分: {self.score}",
            f"最长连击: x{self.max_combo}",
            f"接龙长度: {len(self.chain)}",
        ]
        for i, text in enumerate(cards):
            s = card_font.render(text, True, ACCENT_GOLD if i == 0 else TEXT_COLOR)
            self.screen.blit(s, s.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2 + 10 + i * 35)))

        # 重新开始提示
        hint_font = get_font(18)
        hint_surf = hint_font.render("点击任意位置 或 按空格键 重新开始", True, (160, 180, 220))
        self.screen.blit(hint_surf, hint_surf.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2 + 130)))

    def draw_combo_effect(self):
        """连击特效"""
        if self.combo >= 3:
            colors = [ACCENT_GOLD, ACCENT_GREEN, ACCENT_RED, ACCENT_BLUE, ACCENT_PURPLE]
            color = colors[(self.combo - 3) % len(colors)]
            font = get_font(16 + min(self.combo * 2, 20), bold=True)
            s = font.render(f"🔥 COMBO x{self.combo} 🔥", True, color)
            rect = s.get_rect(center=(SCREEN_WIDTH // 2, 108))
            # 脉冲效果
            scale = 1 + 0.1 * math.sin(pygame.time.get_ticks() * 0.01)
            s2 = pygame.transform.rotozoom(s, 0, scale)
            self.screen.blit(s2, s2.get_rect(center=rect.center))

    def draw(self):
        self.draw_background()
        self.draw_title_bar()
        self.draw_score_panel()
        self.draw_target_panel()
        self.draw_chain_panel()
        self.draw_combo_effect()
        self.draw_input_area()
        self.draw_message()

        # UI组件
        self.input_box.draw(self.screen)
        self.submit_btn.draw(self.screen)
        self.hint_btn.draw(self.screen)
        self.restart_btn.draw(self.screen)
        self.quit_btn.draw(self.screen)

        # 粒子和漂浮文字
        for p in self.particles:
            p.draw(self.screen)
        for ft in self.floating_texts:
            ft.draw(self.screen)

        # 游戏结束覆盖
        if self.state in ("game_over", "victory"):
            self.draw_game_overlay()

        pygame.display.flip()

    # ==================== 更新 & 事件 ====================
    def update(self, dt):
        # 消息计时
        if self.message_timer > 0:
            self.message_timer -= 1

        # 新成语动画
        if self.new_cy_anim > 0:
            self.new_cy_anim -= 1

        # 粒子
        self.particles = [p for p in self.particles if p.life > 0]
        for p in self.particles:
            p.update()

        # 漂浮文字
        self.floating_texts = [ft for ft in self.floating_texts if ft.life > 0]
        for ft in self.floating_texts:
            ft.update()

    def handle_events(self):
        mouse_pos = pygame.mouse.get_pos()
        mouse_pressed = pygame.mouse.get_pressed()[0]
        just_pressed = False

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                self.running = False
                return
            if event.type == pygame.MOUSEBUTTONDOWN:
                just_pressed = True
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_SPACE and self.state in ("game_over", "victory"):
                    self.start_game()
                    return
                if event.key == pygame.K_ESCAPE:
                    self.running = False
                    return
                if event.key == pygame.K_h and self.state == "playing":
                    self.get_hint()
                if event.key == pygame.K_r and pygame.key.get_mods() & pygame.KMOD_CTRL:
                    self.start_game()

            # 输入框
            result = self.input_box.handle_event(event)
            if result == "submit" and self.state == "playing":
                self.submit_player_input()

        # 更新按钮
        self.input_box.update(self.clock.get_time())
        self.submit_btn.update(mouse_pos, mouse_pressed)
        self.hint_btn.update(mouse_pos, mouse_pressed)
        self.restart_btn.update(mouse_pos, mouse_pressed)
        self.quit_btn.update(mouse_pos, mouse_pressed)

        # 按钮点击
        if self.state == "playing":
            if self.submit_btn.is_clicked(mouse_pos, just_pressed):
                self.submit_player_input()
            if self.hint_btn.is_clicked(mouse_pos, just_pressed):
                self.get_hint()
        if self.restart_btn.is_clicked(mouse_pos, just_pressed):
            self.start_game()
        if self.quit_btn.is_clicked(mouse_pos, just_pressed):
            self.running = False

        # 游戏结束点击
        if self.state in ("game_over", "victory") and just_pressed:
            self.start_game()

    def submit_player_input(self):
        text = self.input_box.text.strip()
        if text:
            self.check_player_input(text)
            self.input_box.clear()

    def run(self):
        while self.running:
            dt = self.clock.tick(FPS)
            self.handle_events()
            self.update(dt)
            self.draw()

        pygame.quit()
        sys.exit()


# ==================== 启动 ====================
if __name__ == "__main__":
    print("╔════════════════════════════════════════════╗")
    print("║     🎮 成语接龙游戏 - Pygame 精美版       ║")
    print("╠════════════════════════════════════════════╣")
    print(f"║  📚 词库大小: {len(CHENGYU_SET)} 个成语              ║")
    print(f"║  🔤 拼音类别: {len(CHENGYU_DICT)} 类             ║")
    print("╠════════════════════════════════════════════╣")
    print("║  操作:                                    ║")
    print("║  · 输入4字成语后按回车提交                 ║")
    print("║  · 点击「提示」获取提示(扣5分)            ║")
    print("║  · 空格键 = 重新开始                      ║")
    print("║  · ESC键 = 退出                           ║")
    print("║  · H键 = 获取提示                         ║")
    print("╠════════════════════════════════════════════╣")
    print("║  规则:                                    ║")
    print("║  · 下一成语首字拼音 = 上一成语尾字拼音    ║")
    print("║  · 同音字也可以接龙                       ║")
    print("║  · 每个成语只能用一次                     ║")
    print("║  · 连击越多得分越高                       ║")
    print("╚════════════════════════════════════════════╝")
    print()
    print("正在启动游戏窗口...")

    game = ChengyuGame()
    game.run()
