Files
RongGiuangKT/js/aiGameGenerator.js
2025-10-09 19:25:48 +08:00

1698 lines
58 KiB
JavaScript
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.

/**
* AI智能游戏生成器
* 功能:自动出题、动态难度调整、个性化游戏内容
*/
class AIGameGenerator {
constructor() {
this.isInitialized = false;
this.currentDifficulty = 1; // 1-5级难度
this.studentProfile = null;
this.questionBank = new Map();
this.difficultyHistory = [];
this.performanceHistory = [];
// 题目类型配置
this.questionTypes = {
math: {
addition: { min: 1, max: 20, operators: ['+'] },
subtraction: { min: 1, max: 20, operators: ['-'] },
multiplication: { min: 1, max: 10, operators: ['×'] },
comparison: { min: 1, max: 20, operators: ['>', '<', '='] },
clock: { min: 1, max: 12, operators: ['hour', 'minute'] }
},
language: {
pinyin: { min: 1, max: 10, operators: ['声调', '拼音'] },
word: { min: 1, max: 20, operators: ['组词', '造句'] },
poem: { min: 1, max: 5, operators: ['背诵', '理解'] }
},
life: {
emotion: { min: 1, max: 8, operators: ['识别', '表达'] },
safety: { min: 1, max: 10, operators: ['判断', '选择'] },
daily: { min: 1, max: 15, operators: ['分类', '整理'] }
}
};
// 难度调整参数
this.difficultyParams = {
1: { successRate: 0.9, timeLimit: 30, hints: 3 },
2: { successRate: 0.8, timeLimit: 25, hints: 2 },
3: { successRate: 0.7, timeLimit: 20, hints: 1 },
4: { successRate: 0.6, timeLimit: 15, hints: 0 },
5: { successRate: 0.5, timeLimit: 10, hints: 0 }
};
}
/**
* 初始化AI游戏生成器
*/
async init() {
try {
console.log('🤖 AI游戏生成器初始化中...');
// 加载题目库
await this.loadQuestionBank();
// 加载学生档案
await this.loadStudentProfile();
this.isInitialized = true;
console.log('✅ AI游戏生成器初始化完成');
return true;
} catch (error) {
console.error('❌ AI游戏生成器初始化失败:', error);
return false;
}
}
/**
* 加载学生档案
*/
async loadStudentProfile() {
try {
// 从后端获取学生数据
if (window.apiService) {
const userData = window.userManager?.getCurrentUser();
if (userData) {
const stats = await window.apiService.getStudentStats(userData.id, 30);
this.studentProfile = {
id: userData.id,
name: userData.name,
grade: userData.grade || 2,
strengths: stats.strengths || [],
weaknesses: stats.weaknesses || [],
learningStyle: stats.learningStyle || 'visual',
currentLevel: stats.currentLevel || 1,
totalQuestions: stats.totalQuestions || 0,
correctRate: stats.correctRate || 0.7
};
}
}
// 如果没有后端数据,使用默认配置
if (!this.studentProfile) {
this.studentProfile = {
id: 'default',
name: '学生',
grade: 2,
strengths: ['数学'],
weaknesses: ['语文'],
learningStyle: 'visual',
currentLevel: 1,
totalQuestions: 0,
correctRate: 0.7
};
}
console.log('📊 学生档案加载完成:', this.studentProfile);
} catch (error) {
console.error('❌ 加载学生档案失败:', error);
}
}
/**
* 加载题目库
*/
async loadQuestionBank() {
try {
const response = await fetch('data/questionBank.json');
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const questionBankData = await response.json();
// 将JSON数据转换为Map格式
for (const [subject, types] of Object.entries(questionBankData)) {
this.questionBank.set(subject, types);
}
console.log('📚 题目库加载完成:', this.questionBank);
} catch (error) {
console.error('❌ 加载题目库失败:', error);
// 如果加载失败,使用默认题目库
await this.initializeDefaultQuestionBank();
}
}
/**
* 初始化默认题目库(备用)
*/
async initializeDefaultQuestionBank() {
// 数学题目库
this.questionBank.set('math', {
addition: [
{ question: "2 + 3 = ?", options: ["4", "5", "6", "7"], correct: 1, difficulty: 1 },
{ question: "7 + 8 = ?", options: ["14", "15", "16", "17"], correct: 1, difficulty: 2 }
],
subtraction: [
{ question: "8 - 3 = ?", options: ["4", "5", "6", "7"], correct: 1, difficulty: 1 },
{ question: "15 - 7 = ?", options: ["7", "8", "9", "10"], correct: 1, difficulty: 2 }
]
});
// 语文题目库
this.questionBank.set('language', {
pinyin: [
{ question: "'猫'的拼音是?", options: ["māo", "máo", "mǎo", "mào"], correct: 0, difficulty: 1 }
],
word: [
{ question: "用'美丽'组词", options: ["美丽的花", "美丽的人", "美丽的风景", "以上都对"], correct: 3, difficulty: 2 }
]
});
// 生活题目库
this.questionBank.set('life', {
emotion: [
{ question: "看到好吃的食物,应该是什么表情?", options: ["😊", "😢", "😠", "😴"], correct: 0, difficulty: 1 }
],
safety: [
{ question: "过马路时应该?", options: ["看红绿灯", "直接跑过去", "闭着眼睛", "听音乐"], correct: 0, difficulty: 1 }
]
});
console.log('📚 默认题目库初始化完成');
}
/**
* 生成个性化游戏
*/
generatePersonalizedGame(subject = 'math', gameType = 'quiz', questionCount = 5) {
if (!this.isInitialized) {
console.error('❌ AI游戏生成器未初始化');
return null;
}
console.log(`🎮 生成个性化游戏: ${subject} - ${gameType}`);
const gameConfig = {
id: this.generateGameId(),
subject: subject,
type: gameType,
difficulty: this.currentDifficulty,
questions: [],
timeLimit: this.difficultyParams[this.currentDifficulty].timeLimit,
hints: this.difficultyParams[this.currentDifficulty].hints,
studentProfile: this.studentProfile
};
// 从题目库中获取题目
const questions = this.getQuestionsFromBank(subject, questionCount);
gameConfig.questions = questions;
// 个性化调整
this.personalizeGame(gameConfig);
console.log('✅ 个性化游戏生成完成:', gameConfig);
return gameConfig;
}
/**
* 生成完整的游戏页面
*/
generateGamePage(subject = 'math', gameType = 'quiz', questionCount = 5) {
if (!this.isInitialized) {
console.error('❌ AI游戏生成器未初始化');
return null;
}
console.log(`🎮 生成完整游戏页面: ${subject} - ${gameType}`);
// 生成游戏配置
const gameConfig = this.generatePersonalizedGame(subject, gameType, questionCount);
if (!gameConfig || !gameConfig.questions.length) {
console.error('❌ 无法生成游戏配置');
return null;
}
// 在当前页面内嵌入游戏
this.embedGameInCurrentPage(gameConfig);
console.log('✅ 游戏页面生成完成并已嵌入当前页面');
return gameConfig;
}
/**
* 在当前页面内嵌入游戏
*/
embedGameInCurrentPage(gameConfig) {
const subject = gameConfig.subject;
const gameType = gameConfig.type;
const questions = gameConfig.questions;
const difficulty = gameConfig.difficulty;
// 根据学科确定游戏标题和样式
let gameTitle, gameIntro, gameStyle;
switch (subject) {
case 'math':
if (gameType === 'quiz') {
gameTitle = 'AI数学游戏';
gameIntro = '欢迎来到AI数学游戏我会帮你学习数学知识准备好了吗';
} else {
gameTitle = 'AI数学比大小游戏';
gameIntro = '欢迎来到AI数学比大小游戏我会帮你学习数字比较准备好了吗';
}
gameStyle = this.getMathGameStyle();
break;
case 'language':
gameTitle = 'AI语文拼音游戏';
gameIntro = '欢迎来到AI语文拼音游戏我会帮你学习拼音和声调准备好了吗';
gameStyle = this.getLanguageGameStyle();
break;
case 'life':
gameTitle = 'AI生活安全游戏';
gameIntro = '欢迎来到AI生活安全游戏我会帮你学习生活中的安全知识准备好了吗';
gameStyle = this.getLifeGameStyle();
break;
default:
gameTitle = 'AI智能游戏';
gameIntro = '欢迎来到AI智能游戏我会帮你学习知识准备好了吗';
gameStyle = this.getDefaultGameStyle();
}
// 创建游戏容器
const gameContainer = document.createElement('div');
gameContainer.id = 'ai-game-container';
gameContainer.innerHTML = `
<style>
${gameStyle}
#ai-game-container {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.8);
z-index: 9999;
display: flex;
justify-content: center;
align-items: center;
}
#ai-game-container .game-container {
width: 90%;
max-width: 800px;
max-height: 90%;
overflow-y: auto;
position: relative;
}
.virtual-teacher-sidebar {
position: absolute;
right: -200px;
top: 50%;
transform: translateY(-50%);
width: 180px;
height: 200px;
background: rgba(255, 255, 255, 0.9);
border-radius: 15px;
padding: 20px;
box-shadow: 0 5px 20px rgba(0, 0, 0, 0.2);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.virtual-teacher-avatar {
width: 80px;
height: 80px;
background: linear-gradient(135deg, #ff9aa2, #ffb7b2);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 40px;
margin-bottom: 10px;
box-shadow: 0 3px 10px rgba(0, 0, 0, 0.2);
}
.virtual-teacher-status {
font-size: 14px;
color: #666;
text-align: center;
margin-bottom: 10px;
}
.virtual-teacher-controls {
display: flex;
gap: 10px;
}
.control-btn {
width: 30px;
height: 30px;
border: none;
border-radius: 50%;
background: #f0f0f0;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
font-size: 16px;
transition: all 0.2s ease;
}
.control-btn:hover {
background: #e0e0e0;
transform: scale(1.1);
}
.control-btn.speaking {
background: #4ecdc4;
color: white;
animation: pulse 1s infinite;
}
@keyframes pulse {
0% { transform: scale(1); }
50% { transform: scale(1.1); }
100% { transform: scale(1); }
}
/* 体感交互按钮样式 */
.box-btn {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
display: flex;
align-items: center;
gap: 20px;
background: rgba(255, 255, 255, 0.9);
padding: 15px 30px;
border-radius: 50px;
box-shadow: 0 5px 20px rgba(0, 0, 0, 0.2);
z-index: 1000;
}
.box-btn-left, .box-btn-right {
width: 60px;
height: 60px;
border: none;
border-radius: 50%;
background: linear-gradient(135deg, #4ecdc4, #44a08d);
color: white;
font-size: 18px;
font-weight: bold;
cursor: pointer;
transition: all 0.3s ease;
display: flex;
align-items: center;
justify-content: center;
}
.box-btn-left:hover, .box-btn-right:hover {
transform: scale(1.1);
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
}
.box-btn-left:active, .box-btn-right:active {
transform: scale(0.95);
}
.box-btn-question {
font-size: 16px;
color: #333;
text-align: center;
min-width: 200px;
font-weight: 500;
}
.close-game-btn {
position: absolute;
top: 20px;
right: 20px;
background: #ff6b6b;
color: white;
border: none;
border-radius: 50%;
width: 40px;
height: 40px;
font-size: 20px;
cursor: pointer;
z-index: 10000;
}
.close-game-btn:hover {
background: #ff5252;
}
</style>
<button class="close-game-btn" onclick="closeAIGame()">×</button>
<div class="game-container">
<div class="score-area">
<div>得分: <span id="score">0</span></div>
<div>进度: <span id="progress">0</span>/<span id="total">${questions.length}</span></div>
</div>
<h1>${gameTitle}</h1>
<div class="progress-bar">
<div class="progress-fill" id="progressFill"></div>
</div>
<div class="question-area">
<div class="question" id="questionText">准备开始...</div>
<div class="options" id="optionsContainer">
<!-- 选项将通过JavaScript动态生成 -->
</div>
</div>
<!-- 体感交互按钮容器 -->
<div class="box-btn" id="bodyInteractionBtns" style="display: none;">
<button class="box-btn-left" onclick="selectBodyAnswer('left')" aria-label="选择左侧选项"></button>
<div class="box-btn-question" id="bodyQuestionText">请举起左手或右手选择答案</div>
<button class="box-btn-right" onclick="selectBodyAnswer('right')" aria-label="选择右侧选项"></button>
</div>
<!-- 虚拟猫头鹰侧边栏 -->
<div class="virtual-teacher-sidebar">
<div class="virtual-teacher-avatar" id="virtualTeacherAvatar">🦉</div>
<div class="virtual-teacher-status" id="virtualTeacherStatus">准备就绪</div>
<div class="virtual-teacher-controls">
<button class="control-btn" id="speakBtn" onclick="toggleVirtualTeacher()" title="语音开关">🔊</button>
<button class="control-btn" id="muteBtn" onclick="muteVirtualTeacher()" title="静音">🔇</button>
</div>
</div>
</div>
<div class="message" id="message">
<h2 id="messageTitle">标题</h2>
<p id="messageText">内容</p>
<button class="message-btn" id="messageBtn">继续</button>
</div>
`;
// 添加到页面
document.body.appendChild(gameContainer);
// 初始化游戏逻辑
this.initializeGameLogic(gameConfig, gameTitle, gameIntro);
}
/**
* 初始化游戏逻辑
*/
initializeGameLogic(gameConfig, gameTitle, gameIntro) {
const gameId = gameConfig.id;
const questions = gameConfig.questions;
// DOM元素
const questionText = document.getElementById("questionText");
const optionsContainer = document.getElementById("optionsContainer");
const message = document.getElementById("message");
const messageTitle = document.getElementById("messageTitle");
const messageText = document.getElementById("messageText");
const messageBtn = document.getElementById("messageBtn");
const scoreElement = document.getElementById("score");
const progressElement = document.getElementById("progress");
const totalElement = document.getElementById("total");
const progressFill = document.getElementById("progressFill");
// 游戏状态
let currentQuestionIndex = 0;
let score = 0;
let correctCount = 0;
let gameStarted = false;
let virtualTeacherMuted = false;
// 体感交互元素
const bodyInteractionBtns = document.getElementById("bodyInteractionBtns");
const bodyQuestionText = document.getElementById("bodyQuestionText");
// 虚拟猫头鹰控制函数
function updateVirtualTeacherStatus(status, isSpeaking = false) {
if (virtualTeacherStatus) {
virtualTeacherStatus.textContent = status;
}
if (speakBtn) {
if (isSpeaking) {
speakBtn.classList.add('speaking');
} else {
speakBtn.classList.remove('speaking');
}
}
}
function toggleVirtualTeacher() {
virtualTeacherMuted = !virtualTeacherMuted;
if (virtualTeacherMuted) {
updateVirtualTeacherStatus('已静音');
if (window.gameVirtualTeacher) {
window.gameVirtualTeacher.stopAllSpeech();
}
} else {
updateVirtualTeacherStatus('准备就绪');
}
}
function muteVirtualTeacher() {
virtualTeacherMuted = true;
updateVirtualTeacherStatus('已静音');
if (window.gameVirtualTeacher) {
window.gameVirtualTeacher.stopAllSpeech();
}
}
// 体感交互控制函数
function showBodyInteraction() {
if (bodyInteractionBtns) {
bodyInteractionBtns.style.display = 'flex';
}
}
function hideBodyInteraction() {
if (bodyInteractionBtns) {
bodyInteractionBtns.style.display = 'none';
}
}
function updateBodyQuestionText(text) {
if (bodyQuestionText) {
bodyQuestionText.textContent = text;
}
}
// 体感交互选择答案
function selectBodyAnswer(hand) {
if (currentQuestionIndex >= questions.length) return;
const question = questions[currentQuestionIndex];
let selectedIndex = -1;
// 根据左右手选择对应的选项
if (question.options.length >= 2) {
selectedIndex = hand === 'left' ? 0 : 1;
} else if (question.options.length === 1) {
selectedIndex = 0;
}
if (selectedIndex >= 0) {
selectAnswer(selectedIndex, question);
}
}
// 显示当前题目
function showCurrentQuestion() {
if (currentQuestionIndex >= questions.length) {
endGame();
return;
}
const question = questions[currentQuestionIndex];
questionText.textContent = question.question;
// 清空选项容器
optionsContainer.innerHTML = "";
// 创建选项按钮
question.options.forEach((option, index) => {
const button = document.createElement("button");
button.className = "option-btn";
button.textContent = option;
button.onclick = () => selectAnswer(index, question);
optionsContainer.appendChild(button);
});
// 更新进度
progressElement.textContent = currentQuestionIndex + 1;
progressFill.style.width = `${((currentQuestionIndex + 1) / questions.length) * 100}%`;
// 虚拟老师读题目
if (window.gameVirtualTeacher && !virtualTeacherMuted) {
updateVirtualTeacherStatus('正在读题...', true);
setTimeout(() => {
window.gameVirtualTeacher.readQuestion(question.question);
setTimeout(() => {
updateVirtualTeacherStatus('准备就绪');
}, 2000);
}, 500);
}
// 显示体感交互按钮
showBodyInteraction();
// 更新体感交互提示文本
if (question.options.length >= 2) {
updateBodyQuestionText(`请举起${question.options[0]}${question.options[1]}选择答案`);
} else if (question.options.length === 1) {
updateBodyQuestionText(`请举起任意一只手选择:${question.options[0]}`);
} else {
updateBodyQuestionText('请举起左手或右手选择答案');
}
}
// 选择答案
function selectAnswer(selectedIndex, question) {
if (message.classList.contains("show")) return;
// 隐藏体感交互按钮
hideBodyInteraction();
const isCorrect = selectedIndex === question.correct;
const selectedButton = optionsContainer.children[selectedIndex];
const correctButton = optionsContainer.children[question.correct];
// 显示答案效果
selectedButton.classList.add(isCorrect ? "correct" : "wrong");
if (!isCorrect) {
correctButton.classList.add("correct");
}
// 虚拟老师反馈
if (window.gameVirtualTeacher && !virtualTeacherMuted) {
window.gameVirtualTeacher.stopAllSpeech();
updateVirtualTeacherStatus(isCorrect ? '答对了!' : '再想想...', true);
setTimeout(() => {
if (isCorrect) {
window.gameVirtualTeacher.recordCorrect();
} else {
window.gameVirtualTeacher.recordIncorrect();
}
setTimeout(() => {
updateVirtualTeacherStatus('准备就绪');
}, 1500);
}, 300);
}
// 更新分数
if (isCorrect) {
correctCount++;
score += 10;
scoreElement.textContent = score;
}
// 记录游戏数据
if (gameStarted && window.gameTracker) {
if (isCorrect) {
window.gameTracker.recordCorrect(10, {
question: question.question,
selected: question.options[selectedIndex],
correct: question.options[question.correct],
questionNumber: currentQuestionIndex + 1,
});
} else {
window.gameTracker.recordIncorrect(0, {
question: question.question,
selected: question.options[selectedIndex],
correct: question.options[question.correct],
questionNumber: currentQuestionIndex + 1,
});
}
}
// 显示结果消息
const messageText = isCorrect
? `太棒了!${question.question} 的答案是 ${question.options[question.correct]}`
: `再想想!正确答案是 ${question.options[question.correct]}`;
showMessage(isCorrect, messageText);
if (isCorrect) {
createConfetti();
}
}
// 显示消息
function showMessage(isCorrect, text) {
message.className = "message " + (isCorrect ? "correct" : "wrong");
messageTitle.textContent = isCorrect ? "太棒了!" : "再试一次";
messageText.textContent = text;
message.classList.add("show");
// 自动消失定时器
const autoHideTimer = setTimeout(() => {
nextQuestion();
}, 3000); // 3秒后自动消失
// 点击消息区域也可以消失
message.onclick = () => {
clearTimeout(autoHideTimer);
nextQuestion();
};
}
// 创建彩色纸屑效果
function createConfetti() {
const colors = ["#FF9AA2", "#FFB7B2", "#FFDAC1", "#E2F0CB", "#B5EAD7", "#C7CEEA"];
for (let i = 0; i < 50; i++) {
const confetti = document.createElement("div");
confetti.className = "confetti";
confetti.style.left = `${Math.random() * 100}%`;
confetti.style.backgroundColor = colors[Math.floor(Math.random() * colors.length)];
confetti.style.width = `${Math.random() * 10 + 5}px`;
confetti.style.height = `${Math.random() * 10 + 5}px`;
confetti.style.animation = `confetti-fall ${Math.random() * 2 + 2}s linear forwards`;
confetti.style.animationDelay = `${Math.random() * 0.5}s`;
document.body.appendChild(confetti);
setTimeout(() => {
confetti.remove();
}, 3000);
}
}
// 下一题
function nextQuestion() {
message.classList.remove("show");
currentQuestionIndex++;
showCurrentQuestion();
}
// 结束游戏
function endGame() {
const successRate = (correctCount / questions.length) * 100;
message.className = "message correct";
messageTitle.textContent = "游戏完成!";
messageText.textContent = `恭喜你完成了游戏!\n得分: ${score}\n正确率: ${successRate.toFixed(1)}%`;
message.classList.add("show");
// 虚拟老师游戏结束
if (window.gameVirtualTeacher) {
updateVirtualTeacherStatus('游戏结束!', true);
window.gameVirtualTeacher.gameEnd();
setTimeout(() => {
updateVirtualTeacherStatus('等待重新开始');
}, 2000);
}
// 记录游戏结果
if (gameStarted && window.gameTracker) {
if (successRate >= 80) {
window.gameTracker.recordWin(score, {
totalQuestions: questions.length,
correctCount: correctCount,
successRate: successRate,
});
} else {
window.gameTracker.recordLose(score, {
totalQuestions: questions.length,
correctCount: correctCount,
successRate: successRate,
});
}
}
messageBtn.textContent = "重新开始";
messageBtn.onclick = restartGame;
}
// 重新开始游戏
function restartGame() {
currentQuestionIndex = 0;
score = 0;
correctCount = 0;
scoreElement.textContent = "0";
progressElement.textContent = "0";
progressFill.style.width = "0%";
message.classList.remove("show");
messageBtn.textContent = "继续";
messageBtn.onclick = nextQuestion;
showCurrentQuestion();
}
// 事件监听
messageBtn.addEventListener("click", nextQuestion);
// 初始化游戏
setTimeout(() => {
// 虚拟老师游戏开始
if (window.gameVirtualTeacher) {
updateVirtualTeacherStatus('游戏开始!', true);
window.gameVirtualTeacher.gameStart(gameTitle);
setTimeout(() => {
if (!virtualTeacherMuted) {
window.gameVirtualTeacher.speak(gameIntro);
setTimeout(() => {
updateVirtualTeacherStatus('准备就绪');
}, 3000);
}
}, 1000);
}
// 开始游戏跟踪
if (window.gameTracker) {
window.gameTracker.startGame(gameId, {
gameType: "ai_generated",
difficulty: "adaptive",
subject: gameConfig.subject,
});
}
gameStarted = true;
showCurrentQuestion();
}, 500);
}
/**
* 关闭AI游戏
*/
closeAIGame() {
const gameContainer = document.getElementById('ai-game-container');
if (gameContainer) {
gameContainer.remove();
}
// 停止虚拟老师
if (window.gameVirtualTeacher) {
window.gameVirtualTeacher.stopAllSpeech();
}
console.log('🎮 AI游戏已关闭');
}
/**
* 创建游戏页面HTML
*/
createGamePageHTML(gameConfig) {
const gameId = gameConfig.id;
const subject = gameConfig.subject;
const gameType = gameConfig.type;
const questions = gameConfig.questions;
const difficulty = gameConfig.difficulty;
// 根据学科确定游戏标题和样式
let gameTitle, gameIntro, gameStyle;
switch (subject) {
case 'math':
if (gameType === 'quiz') {
gameTitle = 'AI数学游戏';
gameIntro = '欢迎来到AI数学游戏我会帮你学习数学知识准备好了吗';
} else {
gameTitle = 'AI数学比大小游戏';
gameIntro = '欢迎来到AI数学比大小游戏我会帮你学习数字比较准备好了吗';
}
gameStyle = this.getMathGameStyle();
break;
case 'language':
gameTitle = 'AI语文拼音游戏';
gameIntro = '欢迎来到AI语文拼音游戏我会帮你学习拼音和声调准备好了吗';
gameStyle = this.getLanguageGameStyle();
break;
case 'life':
gameTitle = 'AI生活安全游戏';
gameIntro = '欢迎来到AI生活安全游戏我会帮你学习生活中的安全知识准备好了吗';
gameStyle = this.getLifeGameStyle();
break;
default:
gameTitle = 'AI智能游戏';
gameIntro = '欢迎来到AI智能游戏我会帮你学习知识准备好了吗';
gameStyle = this.getDefaultGameStyle();
}
// 生成游戏HTML
const gameHTML = `
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>${gameTitle}</title>
<!-- 引入必要的脚本 -->
<script src="../../js/apiService.js"></script>
<script src="../../js/dataManager.js"></script>
<script src="../../js/userManager.js"></script>
<script src="../../js/accessTracker.js"></script>
<script src="../../js/gameTracker.js"></script>
<script src="../../js/virtualTeacher.js"></script>
<script src="../../js/gameVirtualTeacher.js"></script>
<style>
${gameStyle}
</style>
</head>
<body>
<div class="game-container">
<div class="score-area">
<div>得分: <span id="score">0</span></div>
<div>进度: <span id="progress">0</span>/<span id="total">${questions.length}</span></div>
</div>
<h1>${gameTitle}</h1>
<div class="progress-bar">
<div class="progress-fill" id="progressFill"></div>
</div>
<div class="question-area">
<div class="question" id="questionText">准备开始...</div>
<div class="options" id="optionsContainer">
<!-- 选项将通过JavaScript动态生成 -->
</div>
</div>
</div>
<div class="message" id="message">
<h2 id="messageTitle">标题</h2>
<p id="messageText">内容</p>
<button class="message-btn" id="messageBtn">继续</button>
</div>
<script>
// 游戏配置
const gameConfig = ${JSON.stringify(gameConfig)};
// DOM元素
const questionText = document.getElementById("questionText");
const optionsContainer = document.getElementById("optionsContainer");
const message = document.getElementById("message");
const messageTitle = document.getElementById("messageTitle");
const messageText = document.getElementById("messageText");
const messageBtn = document.getElementById("messageBtn");
const scoreElement = document.getElementById("score");
const progressElement = document.getElementById("progress");
const totalElement = document.getElementById("total");
const progressFill = document.getElementById("progressFill");
// 游戏状态
let currentQuestionIndex = 0;
let score = 0;
let correctCount = 0;
let gameStarted = false;
let gameId = "${gameId}";
// 显示当前题目
function showCurrentQuestion() {
if (currentQuestionIndex >= gameConfig.questions.length) {
endGame();
return;
}
const question = gameConfig.questions[currentQuestionIndex];
questionText.textContent = question.question;
// 清空选项容器
optionsContainer.innerHTML = "";
// 创建选项按钮
question.options.forEach((option, index) => {
const button = document.createElement("button");
button.className = "option-btn";
button.textContent = option;
button.onclick = () => selectAnswer(index, question);
optionsContainer.appendChild(button);
});
// 更新进度
progressElement.textContent = currentQuestionIndex + 1;
progressFill.style.width = \`\${
((currentQuestionIndex + 1) / gameConfig.questions.length) * 100
}%\`;
}
// 选择答案
function selectAnswer(selectedIndex, question) {
if (message.classList.contains("show")) return;
// 隐藏体感交互按钮
hideBodyInteraction();
const isCorrect = selectedIndex === question.correct;
const selectedButton = optionsContainer.children[selectedIndex];
const correctButton = optionsContainer.children[question.correct];
// 显示答案效果
selectedButton.classList.add(isCorrect ? "correct" : "wrong");
if (!isCorrect) {
correctButton.classList.add("correct");
}
// 虚拟老师反馈
if (window.gameVirtualTeacher && !virtualTeacherMuted) {
window.gameVirtualTeacher.stopAllSpeech();
updateVirtualTeacherStatus(isCorrect ? '答对了!' : '再想想...', true);
setTimeout(() => {
if (isCorrect) {
window.gameVirtualTeacher.recordCorrect();
} else {
window.gameVirtualTeacher.recordIncorrect();
}
setTimeout(() => {
updateVirtualTeacherStatus('准备就绪');
}, 1500);
}, 300);
}
// 更新分数
if (isCorrect) {
correctCount++;
score += 10;
scoreElement.textContent = score;
}
// 记录游戏数据
if (gameStarted && window.gameTracker) {
if (isCorrect) {
window.gameTracker.recordCorrect(10, {
question: question.question,
selected: question.options[selectedIndex],
correct: question.options[question.correct],
questionNumber: currentQuestionIndex + 1,
});
} else {
window.gameTracker.recordIncorrect(0, {
question: question.question,
selected: question.options[selectedIndex],
correct: question.options[question.correct],
questionNumber: currentQuestionIndex + 1,
});
}
}
// 显示结果消息
const messageText = isCorrect
? \`太棒了!\${question.question} 的答案是 \${question.options[question.correct]}\`
: \`再想想!正确答案是 \${question.options[question.correct]}\`;
showMessage(isCorrect, messageText);
if (isCorrect) {
createConfetti();
}
}
// 下一题
function nextQuestion() {
message.classList.remove("show");
currentQuestionIndex++;
showCurrentQuestion();
}
// 结束游戏
function endGame() {
const successRate = (correctCount / gameConfig.questions.length) * 100;
message.className = "message correct";
messageTitle.textContent = "游戏完成!";
messageText.textContent = \`恭喜你完成了游戏!\\n得分: \${score}\\n正确率: \${successRate.toFixed(1)}%\`;
message.classList.add("show");
// 虚拟老师游戏结束
if (window.gameVirtualTeacher) {
updateVirtualTeacherStatus('游戏结束!', true);
window.gameVirtualTeacher.gameEnd();
setTimeout(() => {
updateVirtualTeacherStatus('等待重新开始');
}, 2000);
}
// 记录游戏结果
if (gameStarted && window.gameTracker) {
if (successRate >= 80) {
window.gameTracker.recordWin(score, {
totalQuestions: gameConfig.questions.length,
correctCount: correctCount,
successRate: successRate,
});
} else {
window.gameTracker.recordLose(score, {
totalQuestions: gameConfig.questions.length,
correctCount: correctCount,
successRate: successRate,
});
}
}
messageBtn.textContent = "重新开始";
messageBtn.onclick = restartGame;
// 游戏结束消息不自动消失,需要用户点击
// 清除之前的点击事件
message.onclick = null;
}
// 重新开始游戏
function restartGame() {
currentQuestionIndex = 0;
score = 0;
correctCount = 0;
scoreElement.textContent = "0";
progressElement.textContent = "0";
progressFill.style.width = "0%";
message.classList.remove("show");
messageBtn.textContent = "继续";
messageBtn.onclick = nextQuestion;
showCurrentQuestion();
}
// 事件监听
messageBtn.addEventListener("click", nextQuestion);
// 初始化游戏
setTimeout(() => {
// 虚拟老师游戏开始
if (window.gameVirtualTeacher) {
window.gameVirtualTeacher.gameStart("${gameTitle}");
setTimeout(() => {
window.gameVirtualTeacher.speak("${gameIntro}");
}, 1000);
}
// 开始游戏跟踪
if (window.gameTracker) {
window.gameTracker.startGame(gameId, {
gameType: "ai_generated",
difficulty: "adaptive",
subject: "${subject}",
});
}
gameStarted = true;
showCurrentQuestion();
}, 500);
</script>
</body>
</html>`;
return gameHTML;
}
/**
* 获取数学游戏样式
*/
getMathGameStyle() {
return `
:root {
--primary: #ff9aa2;
--secondary: #ffb7b2;
--accent: #ffdac1;
--correct: #b5ead7;
--wrong: #ff9aa2;
--button: #70a1ff;
--text: #5e5346;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: "Comic Sans MS", "Marker Felt", "微软雅黑", sans-serif;
background-color: #f9f7f0;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background-image: radial-gradient(circle, #f5f5f5 10%, transparent 10%);
background-size: 30px 30px;
overflow: hidden;
}
.game-container {
width: 80%;
background-color: white;
border-radius: 20px;
padding: 30px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
text-align: center;
position: relative;
overflow: hidden;
border: 5px solid #ffdac1;
}
h1 {
color: #ff6b6b;
margin-bottom: 30px;
font-size: 3rem;
text-shadow: 3px 3px 0 #ffdac1;
letter-spacing: 2px;
}
.question-area {
margin: 30px 0;
padding: 20px;
background-color: #f0f8ff;
border-radius: 15px;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
}
.question {
font-size: 4rem;
margin: 20px 0;
color: #5e5346;
font-weight: bold;
}
.options {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 20px;
margin: 30px 0;
}
.option-btn {
padding: 20px;
border-radius: 15px;
background-color: var(--button);
color: white;
border: none;
font-size: 2.5rem;
font-weight: bold;
cursor: pointer;
box-shadow: 0 5px 0 #4a6baf;
transition: all 0.2s ease;
min-height: 80px;
display: flex;
justify-content: center;
align-items: center;
}
.option-btn:hover {
background-color: #5d8eff;
transform: scale(1.05);
}
.option-btn:active {
transform: translateY(5px);
box-shadow: 0 2px 0 #4a6baf;
}
.option-btn.correct {
background-color: var(--correct);
box-shadow: 0 5px 0 #8dd3c7;
}
.option-btn.wrong {
background-color: var(--wrong);
box-shadow: 0 5px 0 #e67e7e;
}
.score-area {
position: absolute;
top: 20px;
right: 20px;
background-color: #fff;
padding: 15px;
border-radius: 10px;
box-shadow: 0 3px 10px rgba(0, 0, 0, 0.1);
font-size: 1.2rem;
font-weight: bold;
color: var(--text);
}
.progress-bar {
width: 100%;
height: 20px;
background-color: #e0e0e0;
border-radius: 10px;
margin: 20px 0;
overflow: hidden;
}
.progress-fill {
height: 100%;
background-color: var(--button);
transition: width 0.3s ease;
border-radius: 10px;
}
.message {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) scale(0);
background-color: white;
padding: 30px;
border-radius: 15px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
z-index: 100;
text-align: center;
max-width: 80%;
transition: all 0.3s ease;
border: 5px solid;
}
.message.show {
transform: translate(-50%, -50%) scale(1);
}
.message.correct {
border-color: #b5ead7;
background-color: #e8f8f3;
}
.message.wrong {
border-color: #ff9aa2;
background-color: #ffeef0;
}
.message h2 {
font-size: 3rem;
margin-bottom: 15px;
}
.message p {
font-size: 2rem;
margin-bottom: 20px;
}
.message-btn {
padding: 10px 20px;
border-radius: 50px;
border: none;
background-color: var(--button);
color: white;
font-size: 2rem;
cursor: pointer;
transition: all 0.2s ease;
}
.message-btn:hover {
background-color: #5d8eff;
transform: scale(1.05);
}
.confetti {
position: absolute;
width: 15px;
height: 15px;
background-color: var(--primary);
opacity: 0;
z-index: 90;
}
@keyframes confetti-fall {
0% {
transform: translateY(-100vh) rotate(0deg);
opacity: 1;
}
100% {
transform: translateY(100vh) rotate(360deg);
opacity: 0;
}
}
@media (max-width: 600px) {
.game-container {
width: 95%;
padding: 20px;
}
h1 {
font-size: 2rem;
}
.question {
font-size: 2.5rem;
}
.options {
grid-template-columns: 1fr;
}
.option-btn {
font-size: 2rem;
}
}`;
}
/**
* 获取语文游戏样式
*/
getLanguageGameStyle() {
return this.getMathGameStyle().replace('--button: #70a1ff;', '--button: #ff6b9d;');
}
/**
* 获取生活游戏样式
*/
getLifeGameStyle() {
return this.getMathGameStyle().replace('--button: #70a1ff;', '--button: #4ecdc4;');
}
/**
* 获取默认游戏样式
*/
getDefaultGameStyle() {
return this.getMathGameStyle();
}
/**
* 从题目库获取题目
*/
getQuestionsFromBank(subject, questionCount) {
const subjectQuestions = this.questionBank.get(subject);
if (!subjectQuestions) {
console.warn(`❌ 未找到学科 ${subject} 的题目库`);
return [];
}
const allQuestions = [];
// 收集所有题目
for (const [type, questions] of Object.entries(subjectQuestions)) {
allQuestions.push(...questions);
}
// 根据难度筛选题目
const suitableQuestions = allQuestions.filter(q =>
q.difficulty <= this.currentDifficulty
);
if (suitableQuestions.length === 0) {
console.warn(`❌ 未找到适合难度 ${this.currentDifficulty} 的题目`);
return [];
}
// 随机选择题目
const selectedQuestions = [];
const shuffled = [...suitableQuestions].sort(() => Math.random() - 0.5);
for (let i = 0; i < Math.min(questionCount, shuffled.length); i++) {
selectedQuestions.push({
...shuffled[i],
id: `q_${Date.now()}_${i}`
});
}
return selectedQuestions;
}
/**
* 选择题目类型
*/
selectQuestionTypes(subject) {
const availableTypes = Object.keys(this.questionTypes[subject] || {});
const studentStrengths = this.studentProfile.strengths;
const studentWeaknesses = this.studentProfile.weaknesses;
// 优先选择学生擅长的类型,但也包含需要练习的类型
let selectedTypes = [];
// 70%选择擅长的类型
const strengthCount = Math.ceil(availableTypes.length * 0.7);
for (let i = 0; i < strengthCount && i < availableTypes.length; i++) {
selectedTypes.push(availableTypes[i]);
}
// 30%选择需要练习的类型
const weaknessCount = availableTypes.length - strengthCount;
for (let i = 0; i < weaknessCount && i < availableTypes.length; i++) {
const type = availableTypes[(strengthCount + i) % availableTypes.length];
if (!selectedTypes.includes(type)) {
selectedTypes.push(type);
}
}
return selectedTypes;
}
/**
* 生成单个题目
*/
generateQuestion(subject, questionType) {
const subjectBank = this.questionBank.get(subject);
if (!subjectBank || !subjectBank[questionType]) {
return null;
}
const questions = subjectBank[questionType];
const suitableQuestions = questions.filter(q => q.difficulty <= this.currentDifficulty);
if (suitableQuestions.length === 0) {
return null;
}
// 随机选择一个题目
const selectedQuestion = suitableQuestions[Math.floor(Math.random() * suitableQuestions.length)];
// 根据当前难度调整题目
return this.adjustQuestionDifficulty(selectedQuestion);
}
/**
* 调整题目难度
*/
adjustQuestionDifficulty(question) {
const adjustedQuestion = { ...question };
// 根据当前难度调整选项数量
if (this.currentDifficulty <= 2) {
// 简单难度:减少选项数量
adjustedQuestion.options = adjustedQuestion.options.slice(0, 3);
} else if (this.currentDifficulty >= 4) {
// 困难难度:增加干扰选项
if (adjustedQuestion.options.length < 4) {
adjustedQuestion.options.push("不知道");
}
}
return adjustedQuestion;
}
/**
* 个性化游戏配置
*/
personalizeGame(gameConfig) {
const profile = this.studentProfile;
// 根据学习风格调整
if (profile.learningStyle === 'visual') {
gameConfig.visualAids = true;
gameConfig.images = true;
} else if (profile.learningStyle === 'auditory') {
gameConfig.audioHints = true;
gameConfig.voiceReading = true;
} else if (profile.learningStyle === 'kinesthetic') {
gameConfig.interactiveElements = true;
gameConfig.handOnActivities = true;
}
// 根据年级调整
if (profile.grade <= 1) {
gameConfig.simpleLanguage = true;
gameConfig.bigFonts = true;
gameConfig.moreHints = true;
} else if (profile.grade >= 3) {
gameConfig.complexQuestions = true;
gameConfig.multipleSteps = true;
}
// 根据正确率调整
if (profile.correctRate < 0.6) {
gameConfig.easierQuestions = true;
gameConfig.moreTime = true;
} else if (profile.correctRate > 0.8) {
gameConfig.challengingQuestions = true;
gameConfig.bonusPoints = true;
}
}
/**
* 动态调整难度
*/
adjustDifficulty(performance) {
const { correct, total, timeSpent, hintsUsed } = performance;
const successRate = correct / total;
const avgTimePerQuestion = timeSpent / total;
// 记录性能历史
this.performanceHistory.push({
timestamp: Date.now(),
successRate,
avgTimePerQuestion,
hintsUsed,
difficulty: this.currentDifficulty
});
// 根据成功率调整难度
if (successRate >= 0.8 && this.currentDifficulty < 5) {
this.currentDifficulty++;
console.log(`📈 难度提升到 ${this.currentDifficulty}`);
} else if (successRate < 0.6 && this.currentDifficulty > 1) {
this.currentDifficulty--;
console.log(`📉 难度降低到 ${this.currentDifficulty}`);
}
// 根据答题速度调整
const expectedTime = this.difficultyParams[this.currentDifficulty].timeLimit;
if (avgTimePerQuestion < expectedTime * 0.5) {
// 答题太快,可能太简单
if (this.currentDifficulty < 5) {
this.currentDifficulty++;
console.log(`⚡ 答题速度过快,难度提升到 ${this.currentDifficulty}`);
}
} else if (avgTimePerQuestion > expectedTime * 1.5) {
// 答题太慢,可能太难
if (this.currentDifficulty > 1) {
this.currentDifficulty--;
console.log(`🐌 答题速度过慢,难度降低到 ${this.currentDifficulty}`);
}
}
return this.currentDifficulty;
}
/**
* 生成游戏ID
*/
generateGameId() {
return `ai_game_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
}
/**
* 获取游戏统计
*/
getGameStats() {
return {
currentDifficulty: this.currentDifficulty,
totalGames: this.performanceHistory.length,
averageSuccessRate: this.performanceHistory.reduce((sum, p) => sum + p.successRate, 0) / this.performanceHistory.length,
difficultyHistory: this.difficultyHistory,
performanceHistory: this.performanceHistory
};
}
/**
* 重置游戏生成器
*/
reset() {
this.currentDifficulty = 1;
this.difficultyHistory = [];
this.performanceHistory = [];
console.log('🔄 AI游戏生成器已重置');
}
}
// 创建全局实例
window.aiGameGenerator = new AIGameGenerator();
// 全局关闭函数
window.closeAIGame = function() {
const gameContainer = document.getElementById('ai-game-container');
if (gameContainer) {
gameContainer.remove();
}
// 停止虚拟老师
if (window.gameVirtualTeacher) {
window.gameVirtualTeacher.stopAllSpeech();
}
console.log('🎮 AI游戏已关闭');
};
// 全局虚拟猫头鹰控制函数
window.toggleVirtualTeacher = function() {
// 这个函数会在游戏内部被定义
if (typeof toggleVirtualTeacher === 'function') {
toggleVirtualTeacher();
}
};
window.muteVirtualTeacher = function() {
// 这个函数会在游戏内部被定义
if (typeof muteVirtualTeacher === 'function') {
muteVirtualTeacher();
}
};
// 全局体感交互函数
window.selectBodyAnswer = function(hand) {
// 这个函数会在游戏内部被定义
if (typeof selectBodyAnswer === 'function') {
selectBodyAnswer(hand);
}
};
// 导出类
if (typeof module !== 'undefined' && module.exports) {
module.exports = AIGameGenerator;
}