601 lines
17 KiB
HTML
601 lines
17 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||
<title>AI语文拼音游戏</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>
|
||
<script src="../../js/aiGameGenerator.js"></script>
|
||
|
||
<style>
|
||
: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;
|
||
}
|
||
}
|
||
</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">5</span></div>
|
||
</div>
|
||
|
||
<h1>AI语文拼音游戏</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>
|
||
// 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 currentGame = null;
|
||
let currentQuestionIndex = 0;
|
||
let score = 0;
|
||
let correctCount = 0;
|
||
let gameStarted = false;
|
||
let gameId = "ai_language_pinyin_" + Date.now();
|
||
|
||
// 初始化AI游戏生成器
|
||
async function initAIGame() {
|
||
try {
|
||
if (!window.aiGameGenerator) {
|
||
throw new Error("AI游戏生成器未加载");
|
||
}
|
||
|
||
await window.aiGameGenerator.init();
|
||
console.log("✅ AI游戏生成器初始化成功");
|
||
|
||
// 生成语文拼音游戏
|
||
currentGame = window.aiGameGenerator.generatePersonalizedGame(
|
||
"language",
|
||
"quiz",
|
||
5
|
||
);
|
||
|
||
if (currentGame && currentGame.questions.length > 0) {
|
||
// 筛选拼音题目
|
||
const pinyinQuestions = currentGame.questions.filter(
|
||
(q) => q.question.includes("拼音") || q.question.includes("声调")
|
||
);
|
||
|
||
if (pinyinQuestions.length > 0) {
|
||
currentGame.questions = pinyinQuestions.slice(0, 5);
|
||
}
|
||
|
||
totalElement.textContent = currentGame.questions.length;
|
||
console.log("🎮 AI语文拼音游戏生成成功:", currentGame);
|
||
return true;
|
||
} else {
|
||
throw new Error("无法生成游戏题目");
|
||
}
|
||
} catch (error) {
|
||
console.error("❌ AI游戏初始化失败:", error);
|
||
return false;
|
||
}
|
||
}
|
||
|
||
// 显示当前题目
|
||
function showCurrentQuestion() {
|
||
if (
|
||
!currentGame ||
|
||
currentQuestionIndex >= currentGame.questions.length
|
||
) {
|
||
endGame();
|
||
return;
|
||
}
|
||
|
||
const question = currentGame.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) / currentGame.questions.length) * 100
|
||
}%`;
|
||
}
|
||
|
||
// 选择答案
|
||
function selectAnswer(selectedIndex, question) {
|
||
if (message.classList.contains("show")) return;
|
||
|
||
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) {
|
||
window.gameVirtualTeacher.stopAllSpeech();
|
||
setTimeout(() => {
|
||
if (isCorrect) {
|
||
window.gameVirtualTeacher.recordCorrect();
|
||
} else {
|
||
window.gameVirtualTeacher.recordIncorrect();
|
||
}
|
||
}, 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");
|
||
}
|
||
|
||
// 创建彩色纸屑效果
|
||
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 / currentGame.questions.length) * 100;
|
||
|
||
message.className = "message correct";
|
||
messageTitle.textContent = "游戏完成!";
|
||
messageText.textContent = `恭喜你完成了游戏!\n得分: ${score}\n正确率: ${successRate.toFixed(
|
||
1
|
||
)}%`;
|
||
message.classList.add("show");
|
||
|
||
// 虚拟老师游戏结束
|
||
if (window.gameVirtualTeacher) {
|
||
window.gameVirtualTeacher.gameEnd();
|
||
}
|
||
|
||
// 记录游戏结果
|
||
if (gameStarted && window.gameTracker) {
|
||
if (successRate >= 80) {
|
||
window.gameTracker.recordWin(score, {
|
||
totalQuestions: currentGame.questions.length,
|
||
correctCount: correctCount,
|
||
successRate: successRate,
|
||
});
|
||
} else {
|
||
window.gameTracker.recordLose(score, {
|
||
totalQuestions: currentGame.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);
|
||
|
||
// 页面加载完成后初始化
|
||
document.addEventListener("DOMContentLoaded", async function () {
|
||
// 初始化虚拟老师
|
||
if (window.gameVirtualTeacher) {
|
||
window.gameVirtualTeacher
|
||
.init({
|
||
intro:
|
||
"欢迎来到AI语文拼音游戏!我会帮你学习拼音和声调,准备好了吗?",
|
||
})
|
||
.then(() => {
|
||
console.log("🦉 AI语文拼音游戏虚拟老师初始化成功");
|
||
})
|
||
.catch((error) => {
|
||
console.error("❌ 虚拟老师初始化失败:", error);
|
||
});
|
||
}
|
||
|
||
// 初始化后端集成
|
||
Promise.all([window.userManager.init(), window.dataManager.init()])
|
||
.then(async () => {
|
||
console.log("后端集成初始化完成");
|
||
|
||
// 初始化AI游戏
|
||
const success = await initAIGame();
|
||
if (success) {
|
||
// 开始游戏跟踪
|
||
if (window.gameTracker) {
|
||
window.gameTracker.startGame(gameId, {
|
||
gameType: "ai_language_pinyin",
|
||
difficulty: "adaptive",
|
||
});
|
||
}
|
||
|
||
// 虚拟老师游戏开始
|
||
if (window.gameVirtualTeacher) {
|
||
window.gameVirtualTeacher.gameStart("AI语文拼音游戏");
|
||
setTimeout(() => {
|
||
window.gameVirtualTeacher.speak(
|
||
"欢迎来到AI语文拼音游戏!我会帮你学习拼音和声调,准备好了吗?"
|
||
);
|
||
}, 1000);
|
||
}
|
||
|
||
gameStarted = true;
|
||
showCurrentQuestion();
|
||
} else {
|
||
showMessage(false, "游戏初始化失败,请刷新页面重试");
|
||
}
|
||
})
|
||
.catch((error) => {
|
||
console.error("后端集成初始化失败:", error);
|
||
showMessage(false, "系统初始化失败,请刷新页面重试");
|
||
});
|
||
});
|
||
</script>
|
||
</body>
|
||
</html>
|