import streamlit as st import requests from pydantic import BaseModel, Field from dotenv import load_dotenv import os import json # 加载环境变量 load_dotenv() # 设置API密钥 DEEPSEEK_API_KEY = os.getenv("DEEPSEEK_API_KEY", "sk-b04b9134730c4375a5789e2e00978ee0") API_BASE_URL = "https://api.deepseek.com/v1/chat/completions" # 定义Pydantic数据模型 class IdiomResponse(BaseModel): idiom: str = Field(..., description="成语") meaning: str = Field(..., description="成语含义") pinyin: str = Field(..., description="拼音") explanation: str = Field(..., description="详细解释") class GameState(BaseModel): current_idiom: str = Field(default="", description="当前成语") history: list = Field(default_factory=list, description="成语接龙历史") score: int = Field(default=0, description="得分") is_game_over: bool = Field(default=False, description="游戏是否结束") # 初始化游戏状态 if "game_state" not in st.session_state: st.session_state.game_state = GameState() # 调用DeepSeek API生成下一个成语 def get_next_idiom(last_idiom: str) -> IdiomResponse: headers = { "Authorization": f"Bearer {DEEPSEEK_API_KEY}", "Content-Type": "application/json" } # 构建提示词 prompt = f"请你作为一个成语接龙游戏的助手,根据最后一个成语的最后一个字,生成下一个成语。上一个成语是:{last_idiom}。请严格按照JSON格式返回:{{\"idiom\": \"成语\", \"meaning\": \"简短含义\", \"pinyin\": \"拼音\", \"explanation\": \"详细解释\"}},不要添加任何其他内容。" payload = { "model": "deepseek-chat", "messages": [ {"role": "system", "content": "你是一个中文成语专家,精通成语接龙游戏。"}, {"role": "user", "content": prompt} ], "temperature": 0.3, "response_format": {"type": "json_object"} } response = requests.post(API_BASE_URL, headers=headers, json=payload, timeout=30.0) response.raise_for_status() data = response.json() # 解析API响应 content = data["choices"][0]["message"]["content"] return IdiomResponse.model_validate_json(content) # 检查用户输入的成语是否有效 def validate_user_idiom(user_idiom: str, last_idiom: str) -> bool: if len(user_idiom) != 4: return False if last_idiom and user_idiom[0] != last_idiom[-1]: return False return True # 重置游戏 def reset_game(): st.session_state.game_state = GameState() # 主应用界面 st.title("🎯 成语接龙游戏") st.write("与AI一起玩成语接龙,看看谁的成语储备更丰富!") # 游戏控制区 col1, col2 = st.columns(2) with col1: if st.button("🎮 开始新游戏", type="primary"): reset_game() with col2: if st.button("📊 查看规则"): st.info(""" **成语接龙规则:** 1. 游戏开始时,AI会先出一个成语 2. 玩家需要接一个以AI成语最后一个字开头的四字成语 3. AI会继续接玩家的成语 4. 如此循环,直到一方无法接出成语 5. 每成功接一个成语,得分+1 """) # 游戏状态显示 st.markdown("---") # 初始状态:AI先出成语 if not st.session_state.game_state.current_idiom and not st.session_state.game_state.is_game_over: with st.spinner("🤖 AI正在思考第一个成语..."): try: # 使用一个默认的起始成语让AI开始 initial_idiom = get_next_idiom("开门见山") st.session_state.game_state.current_idiom = initial_idiom.idiom st.session_state.game_state.history.append({ "role": "ai", "idiom": initial_idiom.idiom, "meaning": initial_idiom.meaning, "pinyin": initial_idiom.pinyin, "explanation": initial_idiom.explanation }) except Exception as e: st.error(f"🤖 AI出错了:{str(e)}") st.session_state.game_state.is_game_over = True # 游戏进行中 if st.session_state.game_state.current_idiom and not st.session_state.game_state.is_game_over: # 显示当前成语 current = st.session_state.game_state.history[-1] st.markdown(f"\n**🤖 AI 出的成语:** {current['idiom']}") st.caption(f"拼音:{current['pinyin']} | 含义:{current['meaning']}") with st.expander("查看详细解释"): st.write(current['explanation']) # 用户输入区 user_input = st.text_input( f"\n请接一个以'**{st.session_state.game_state.current_idiom[-1]}**'开头的四字成语:", placeholder="例如:xxx", key="user_idiom_input" ) # 提交按钮 if st.button("✅ 提交", key="submit_btn"): if validate_user_idiom(user_input, st.session_state.game_state.current_idiom): # 验证通过,记录用户的成语 st.session_state.game_state.history.append({ "role": "user", "idiom": user_input, "meaning": "", "pinyin": "" }) st.session_state.game_state.score += 1 # AI 接成语 with st.spinner("🤖 AI正在思考..."): try: next_idiom = get_next_idiom(user_input) st.session_state.game_state.current_idiom = next_idiom.idiom st.session_state.game_state.history.append({ "role": "ai", "idiom": next_idiom.idiom, "meaning": next_idiom.meaning, "pinyin": next_idiom.pinyin, "explanation": next_idiom.explanation }) st.rerun() except Exception as e: st.success("🎉 AI接不上来,你赢了!") st.session_state.game_state.is_game_over = True else: st.error("❌ 无效的成语!请确保是四字成语且第一个字与上一个成语的最后一个字相同。") # 游戏结束 if st.session_state.game_state.is_game_over: st.markdown("\n---") st.success(f"🎉 游戏结束!你的得分:{st.session_state.game_state.score}") # 显示历史记录 if st.session_state.game_state.history: st.markdown("\n📝 **游戏历史:**") for i, item in enumerate(st.session_state.game_state.history): role = "🤖 AI" if item["role"] == "ai" else "👤 你" st.write(f"{i+1}. {role}: {item['idiom']}") # 侧边栏信息 with st.sidebar: st.markdown("## 📊 游戏统计") st.write(f"**当前得分:** {st.session_state.game_state.score}") st.write(f"**接龙次数:** {len(st.session_state.game_state.history)}") if st.session_state.game_state.history: st.markdown("\n## 📖 最近成语") for i, item in enumerate(reversed(st.session_state.game_state.history[-5:])): role = "🤖" if item["role"] == "ai" else "👤" st.write(f"{role} {item['idiom']}") st.markdown("\n## 📌 提示") st.write("- 确保输入的是标准四字成语") st.write("- 注意汉字的正确写法") st.write("- 可以使用同音字进行接龙")