初始化
This commit is contained in:
244
games/quiz.py
Normal file
244
games/quiz.py
Normal file
@@ -0,0 +1,244 @@
|
||||
"""问答游戏"""
|
||||
import json
|
||||
import random
|
||||
import logging
|
||||
from pathlib import Path
|
||||
from games.base import BaseGame
|
||||
from utils.parser import CommandParser
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class QuizGame(BaseGame):
|
||||
"""问答游戏"""
|
||||
|
||||
def __init__(self):
|
||||
"""初始化游戏"""
|
||||
super().__init__()
|
||||
self._questions = None
|
||||
|
||||
def _load_questions(self):
|
||||
"""懒加载题库"""
|
||||
if self._questions is None:
|
||||
try:
|
||||
data_file = Path(__file__).parent.parent / "data" / "quiz.json"
|
||||
with open(data_file, 'r', encoding='utf-8') as f:
|
||||
data = json.load(f)
|
||||
self._questions = data.get('questions', [])
|
||||
logger.info(f"题库加载完成,共 {len(self._questions)} 道题")
|
||||
except Exception as e:
|
||||
logger.error(f"加载题库失败: {e}")
|
||||
self._questions = []
|
||||
|
||||
async def handle(self, command: str, chat_id: int, user_id: int) -> str:
|
||||
"""处理问答指令
|
||||
|
||||
Args:
|
||||
command: 指令,如 ".quiz" 或 ".quiz 答案"
|
||||
chat_id: 会话ID
|
||||
user_id: 用户ID
|
||||
|
||||
Returns:
|
||||
回复消息
|
||||
"""
|
||||
try:
|
||||
# 加载题库
|
||||
self._load_questions()
|
||||
|
||||
if not self._questions:
|
||||
return "❌ 题库加载失败"
|
||||
|
||||
# 提取参数
|
||||
_, args = CommandParser.extract_command_args(command)
|
||||
args = args.strip()
|
||||
|
||||
# 检查是否有进行中的题目
|
||||
state = self.db.get_game_state(chat_id, user_id, 'quiz')
|
||||
|
||||
if not args:
|
||||
# 没有参数,出新题或显示当前题
|
||||
if state:
|
||||
# 显示当前题目
|
||||
state_data = state['state_data']
|
||||
return self._show_current_question(state_data)
|
||||
else:
|
||||
# 出新题
|
||||
return self._new_question(chat_id, user_id)
|
||||
else:
|
||||
# 有参数,检查答案
|
||||
if state:
|
||||
return self._check_answer(chat_id, user_id, args)
|
||||
else:
|
||||
# 没有进行中的题目
|
||||
return "⚠️ 当前没有题目,输入 `.quiz` 获取新题目"
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"处理问答指令错误: {e}", exc_info=True)
|
||||
return f"❌ 处理指令出错: {str(e)}"
|
||||
|
||||
def _new_question(self, chat_id: int, user_id: int) -> str:
|
||||
"""出新题目
|
||||
|
||||
Args:
|
||||
chat_id: 会话ID
|
||||
user_id: 用户ID
|
||||
|
||||
Returns:
|
||||
题目信息
|
||||
"""
|
||||
# 随机选择一道题
|
||||
question = random.choice(self._questions)
|
||||
|
||||
# 保存游戏状态
|
||||
state_data = {
|
||||
'question_id': question['id'],
|
||||
'question': question['question'],
|
||||
'answer': question['answer'],
|
||||
'keywords': question['keywords'],
|
||||
'hint': question.get('hint', ''),
|
||||
'category': question.get('category', ''),
|
||||
'attempts': 0,
|
||||
'max_attempts': 3
|
||||
}
|
||||
self.db.save_game_state(chat_id, user_id, 'quiz', state_data)
|
||||
|
||||
# 格式化输出
|
||||
text = f"## 📝 问答题\n\n"
|
||||
text += f"**分类**:{question.get('category', '未分类')}\n\n"
|
||||
text += f"**问题**:{question['question']}\n\n"
|
||||
text += f"💡 你有 **3** 次回答机会\n\n"
|
||||
text += f"输入 `.quiz 答案` 来回答"
|
||||
|
||||
return text
|
||||
|
||||
def _show_current_question(self, state_data: dict) -> str:
|
||||
"""显示当前题目
|
||||
|
||||
Args:
|
||||
state_data: 游戏状态数据
|
||||
|
||||
Returns:
|
||||
题目信息
|
||||
"""
|
||||
attempts = state_data['attempts']
|
||||
max_attempts = state_data['max_attempts']
|
||||
remaining = max_attempts - attempts
|
||||
|
||||
text = f"## 📝 当前题目\n\n"
|
||||
text += f"**分类**:{state_data.get('category', '未分类')}\n\n"
|
||||
text += f"**问题**:{state_data['question']}\n\n"
|
||||
text += f"**剩余机会**:{remaining} 次\n\n"
|
||||
|
||||
# 如果已经尝试过,显示提示
|
||||
if attempts > 0 and state_data.get('hint'):
|
||||
text += f"💡 提示:{state_data['hint']}\n\n"
|
||||
|
||||
text += f"输入 `.quiz 答案` 来回答"
|
||||
|
||||
return text
|
||||
|
||||
def _check_answer(self, chat_id: int, user_id: int, user_answer: str) -> str:
|
||||
"""检查答案
|
||||
|
||||
Args:
|
||||
chat_id: 会话ID
|
||||
user_id: 用户ID
|
||||
user_answer: 用户答案
|
||||
|
||||
Returns:
|
||||
结果信息
|
||||
"""
|
||||
state = self.db.get_game_state(chat_id, user_id, 'quiz')
|
||||
if not state:
|
||||
return "⚠️ 当前没有题目"
|
||||
|
||||
state_data = state['state_data']
|
||||
correct_answer = state_data['answer']
|
||||
keywords = state_data['keywords']
|
||||
attempts = state_data['attempts']
|
||||
max_attempts = state_data['max_attempts']
|
||||
|
||||
# 更新尝试次数
|
||||
attempts += 1
|
||||
|
||||
# 检查答案(关键词匹配)
|
||||
user_answer_lower = user_answer.lower().strip()
|
||||
is_correct = False
|
||||
|
||||
for keyword in keywords:
|
||||
if keyword.lower() in user_answer_lower:
|
||||
is_correct = True
|
||||
break
|
||||
|
||||
if is_correct:
|
||||
# 回答正确
|
||||
self.db.delete_game_state(chat_id, user_id, 'quiz')
|
||||
self.db.update_game_stats(user_id, 'quiz', win=True)
|
||||
|
||||
text = f"## 🎉 回答正确!\n\n"
|
||||
text += f"**答案**:<font color='#4CAF50'>{correct_answer}</font>\n\n"
|
||||
text += f"**用了**:{attempts} 次机会\n\n"
|
||||
|
||||
if attempts == 1:
|
||||
text += "太棒了!一次就答对!🎯"
|
||||
else:
|
||||
text += "虽然用了几次机会,但最终还是答对了!💪"
|
||||
|
||||
text += "\n\n输入 `.quiz` 获取下一题"
|
||||
|
||||
return text
|
||||
|
||||
# 回答错误
|
||||
if attempts >= max_attempts:
|
||||
# 机会用完
|
||||
self.db.delete_game_state(chat_id, user_id, 'quiz')
|
||||
self.db.update_game_stats(user_id, 'quiz', loss=True)
|
||||
|
||||
text = f"## ❌ 很遗憾,答错了\n\n"
|
||||
text += f"**正确答案**:<font color='#F44336'>{correct_answer}</font>\n\n"
|
||||
text += "下次加油!\n\n"
|
||||
text += "输入 `.quiz` 获取下一题"
|
||||
|
||||
return text
|
||||
|
||||
# 还有机会
|
||||
state_data['attempts'] = attempts
|
||||
self.db.save_game_state(chat_id, user_id, 'quiz', state_data)
|
||||
|
||||
remaining = max_attempts - attempts
|
||||
|
||||
text = f"## ❌ 答案不对\n\n"
|
||||
text += f"**你的答案**:{user_answer}\n\n"
|
||||
text += f"**剩余机会**:{remaining} 次\n\n"
|
||||
|
||||
# 显示提示
|
||||
if state_data.get('hint'):
|
||||
text += f"💡 提示:{state_data['hint']}\n\n"
|
||||
|
||||
text += "再想想,继续回答吧!"
|
||||
|
||||
return text
|
||||
|
||||
def get_help(self) -> str:
|
||||
"""获取帮助信息"""
|
||||
return """## 📝 问答游戏
|
||||
|
||||
### 基础用法
|
||||
- `.quiz` - 获取新题目
|
||||
- `.quiz 答案` - 回答问题
|
||||
|
||||
### 游戏规则
|
||||
- 每道题有 3 次回答机会
|
||||
- 答错会显示提示
|
||||
- 回答正确可继续下一题
|
||||
|
||||
### 示例
|
||||
```
|
||||
.quiz # 获取题目
|
||||
.quiz Python # 回答
|
||||
.quiz 北京 # 回答
|
||||
```
|
||||
|
||||
💡 提示:题目涵盖编程、地理、常识等多个领域
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user