Files
RGKT/rg-09112127/html/play/AI数学加法游戏.html
2025-10-10 19:35:04 +08:00

702 lines
19 KiB
HTML
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.

<!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>
<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">3</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 currentQuestionIndex = 0;
let score = 0;
let correctCount = 0;
let gameStarted = false;
// 10以内加减法题目集合
const gameQuestions = [
{
question: "3 + 5 = ?",
options: ["6", "8", "9", "7"],
correct: 1, // 对应 "8"
explanation: "3 + 5 = 8"
},
{
question: "9 - 4 = ?",
options: ["4", "5", "6", "3"],
correct: 1, // 对应 "5"
explanation: "9 - 4 = 5"
},
{
question: "6 + 2 = ?",
options: ["7", "8", "9", "10"],
correct: 1, // 对应 "8"
explanation: "6 + 2 = 8"
}
];
// 随机打乱题目选项的函数
function shuffleOptions(question) {
const correctAnswer = question.options[question.correct];
const shuffledOptions = [...question.options];
// 使用Fisher-Yates算法打乱数组
for (let i = shuffledOptions.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[shuffledOptions[i], shuffledOptions[j]] = [shuffledOptions[j], shuffledOptions[i]];
}
// 找到正确答案的新位置
const newCorrectIndex = shuffledOptions.indexOf(correctAnswer);
return {
...question,
options: shuffledOptions,
correct: newCorrectIndex
};
}
// 生成更多随机题目的函数
function generateRandomQuestion() {
const isAddition = Math.random() > 0.5;
let num1, num2, answer, question;
if (isAddition) {
// 加法确保结果不超过10
num1 = Math.floor(Math.random() * 6) + 1; // 1-6
num2 = Math.floor(Math.random() * (10 - num1)) + 1; // 确保结果≤10
answer = num1 + num2;
question = `${num1} + ${num2} = ?`;
} else {
// 减法:确保结果不为负数
num1 = Math.floor(Math.random() * 9) + 2; // 2-10
num2 = Math.floor(Math.random() * num1) + 1; // 1到num1-1
answer = num1 - num2;
question = `${num1} - ${num2} = ?`;
}
// 生成错误选项
const wrongOptions = [];
while (wrongOptions.length < 3) {
let wrongAnswer;
if (isAddition) {
wrongAnswer = answer + (Math.random() > 0.5 ? 1 : -1) * (Math.floor(Math.random() * 3) + 1);
} else {
wrongAnswer = answer + (Math.random() > 0.5 ? 1 : -1) * (Math.floor(Math.random() * 3) + 1);
}
if (wrongAnswer >= 0 && wrongAnswer <= 20 && wrongAnswer !== answer && !wrongOptions.includes(wrongAnswer)) {
wrongOptions.push(wrongAnswer);
}
}
const options = [answer, ...wrongOptions].map(String);
return shuffleOptions({
question: question,
options: options,
correct: 0, // 初始正确答案在第一位
explanation: `${question.replace('?', answer)}`
});
}
// 初始化游戏题目
function initializeGame() {
// 使用预设题目和随机生成的题目
const allQuestions = [...gameQuestions];
// 为每个题目重新打乱选项
for (let i = 0; i < allQuestions.length; i++) {
allQuestions[i] = shuffleOptions(allQuestions[i]);
}
return allQuestions;
}
// 当前游戏题目
let currentGame = initializeGame();
// 显示当前题目
function showCurrentQuestion() {
if (currentQuestionIndex >= currentGame.length) {
endGame();
return;
}
const question = currentGame[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.length) * 100}%`;
// 虚拟老师朗读题目
if (window.gameVirtualTeacher) {
window.gameVirtualTeacher.stopAllSpeech();
setTimeout(() => {
const questionNumber = currentQuestionIndex + 1;
const readableQuestion = question.question.replace('=', '等于').replace('?', '多少');
window.gameVirtualTeacher.speak(`${questionNumber}题:${readableQuestion}`);
}, 800);
}
}
// 选择答案
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];
// 禁用所有按钮
Array.from(optionsContainer.children).forEach(btn => {
btn.style.pointerEvents = 'none';
});
// 显示答案效果
selectedButton.classList.add(isCorrect ? "correct" : "wrong");
if (!isCorrect) {
correctButton.classList.add("correct");
}
// 虚拟老师反馈
if (window.gameVirtualTeacher) {
window.gameVirtualTeacher.stopAllSpeech();
setTimeout(() => {
if (isCorrect) {
const encouragements = [
"太棒了!答对了!",
"很好!你答对了!",
"正确!做得很棒!",
"厉害!继续保持!"
];
const randomEncouragement = encouragements[Math.floor(Math.random() * encouragements.length)];
window.gameVirtualTeacher.speak(randomEncouragement);
window.gameVirtualTeacher.recordCorrect();
} else {
const hints = [
"没关系,再想想看!",
"不要紧,下次会更好!",
"正确答案是" + question.options[question.correct],
"让我们继续努力!"
];
const randomHint = hints[Math.floor(Math.random() * hints.length)];
window.gameVirtualTeacher.speak(randomHint);
window.gameVirtualTeacher.recordIncorrect();
}
}, 300);
}
// 更新分数
if (isCorrect) {
correctCount++;
score += 10;
scoreElement.textContent = score;
}
// 显示结果消息
const messageText = isCorrect
? `太棒了!${question.explanation}`
: `再想想!正确答案是 ${question.explanation}`;
setTimeout(() => {
showMessage(isCorrect, messageText);
if (isCorrect) {
createConfetti();
}
}, 500);
}
// 显示消息
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");
// 重新启用按钮
Array.from(optionsContainer.children).forEach(btn => {
btn.style.pointerEvents = 'auto';
btn.classList.remove('correct', 'wrong');
});
currentQuestionIndex++;
showCurrentQuestion();
}
// 结束游戏
function endGame() {
const successRate = (correctCount / currentGame.length) * 100;
message.className = "message correct";
messageTitle.textContent = "游戏完成!";
messageText.textContent = `恭喜你完成了游戏!\n得分: ${score}\n正确率: ${successRate.toFixed(1)}%\n\n${getEncouragementMessage(successRate)}`;
message.classList.add("show");
// 虚拟老师游戏结束语音
if (window.gameVirtualTeacher) {
window.gameVirtualTeacher.stopAllSpeech();
setTimeout(() => {
let endMessage = `游戏完成!你的得分是${score}分,正确率${successRate.toFixed(1)}%。`;
if (successRate === 100) {
endMessage += "太棒了!你全部答对了,你是数学小天才!";
} else if (successRate >= 66) {
endMessage += "做得很好!继续加油,你会越来越棒的!";
} else {
endMessage += "不错的开始!多多练习,下次一定会更好!";
}
window.gameVirtualTeacher.speak(endMessage);
window.gameVirtualTeacher.gameEnd();
}, 1000);
}
messageBtn.textContent = "重新开始";
messageBtn.onclick = restartGame;
// 创建庆祝动画
createConfetti();
}
// 根据成绩给出鼓励语
function getEncouragementMessage(successRate) {
if (successRate === 100) {
return "完美!你是数学小天才!🌟";
} else if (successRate >= 66) {
return "做得很好!继续加油!👏";
} else {
return "不错的开始!多练习会更棒!💪";
}
}
// 重新开始游戏
function restartGame() {
currentQuestionIndex = 0;
score = 0;
correctCount = 0;
scoreElement.textContent = "0";
progressElement.textContent = "0";
progressFill.style.width = "0%";
// 重新初始化游戏题目(重新打乱选项)
currentGame = initializeGame();
message.classList.remove("show");
messageBtn.textContent = "继续";
messageBtn.onclick = nextQuestion;
// 虚拟老师重新开始游戏
if (window.gameVirtualTeacher) {
window.gameVirtualTeacher.stopAllSpeech();
window.gameVirtualTeacher.gameStart("AI数学加减法游戏");
setTimeout(() => {
window.gameVirtualTeacher.speak("好的!让我们重新开始挑战吧!");
}, 500);
}
showCurrentQuestion();
}
// 事件监听
messageBtn.addEventListener("click", nextQuestion);
// 页面加载完成后初始化
document.addEventListener("DOMContentLoaded", function () {
console.log("🎮 数学加减法游戏初始化完成");
// 初始化虚拟老师
if (window.gameVirtualTeacher) {
window.gameVirtualTeacher
.init({
intro: "欢迎来到AI数学加减法游戏我会帮你学习10以内的加减法运算还会为你朗读每道题目。准备好了吗",
})
.then(() => {
console.log("🦉 AI数学加减法游戏虚拟老师初始化成功");
})
.catch((error) => {
console.error("❌ 虚拟老师初始化失败:", error);
});
}
// 初始化后端集成(如果存在)
const initBackend = async () => {
try {
if (window.userManager && window.dataManager) {
await Promise.all([window.userManager.init(), window.dataManager.init()]);
console.log("后端集成初始化完成");
}
} catch (error) {
console.warn("后端集成初始化失败,但游戏仍可正常运行:", error);
}
};
initBackend();
// 显示开始消息
setTimeout(() => {
message.className = "message correct";
messageTitle.textContent = "欢迎!";
messageText.textContent = "我会为你朗读每道题目!\n让我们开始吧";
message.classList.add("show");
// 虚拟老师欢迎语音
if (window.gameVirtualTeacher) {
setTimeout(() => {
window.gameVirtualTeacher.speak("欢迎来到数学加减法游戏我会帮你学习10以内的加减法还会为你朗读每道题目。准备好开始了吗");
}, 100);
}
messageBtn.textContent = "开始游戏";
messageBtn.onclick = () => {
message.classList.remove("show");
messageBtn.textContent = "继续";
messageBtn.onclick = nextQuestion;
gameStarted = true;
// 虚拟老师游戏开始
if (window.gameVirtualTeacher) {
window.gameVirtualTeacher.gameStart("AI数学加减法游戏");
}
showCurrentQuestion();
};
}, 500);
});
</script>
</body>
</html>