Files
WPSBot/games/quiz.py
2025-10-28 13:00:35 +08:00

245 lines
7.7 KiB
Python
Raw Permalink 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 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 北京 # 回答
```
💡 提示:题目涵盖编程、地理、常识等多个领域
"""