zshxsy/idiom_game.py

192 lines
7.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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("- 可以使用同音字进行接龙")