zylyzghc/script.js

401 lines
13 KiB
JavaScript
Raw Normal View History

2026-01-08 21:14:46 +08:00
// 英语学习网页主脚本
// 游戏状态
let gameState = {
currentSceneIndex: 0,
currentDialogIndex: 0,
score: 0,
totalQuestions: 0,
correctAnswers: 0
};
// DOM元素
let elements;
// 在DOM加载完成后获取DOM元素
function getDomElements() {
elements = {
scoreElement: document.getElementById('score'),
progressElement: document.getElementById('progress'),
sceneTitle: document.getElementById('scene-title'),
sceneDescription: document.getElementById('scene-description'),
sceneImage: document.getElementById('scene-image'),
conversation: document.getElementById('conversation'),
questionArea: document.getElementById('question-area'),
questionText: document.getElementById('question-text'),
options: document.querySelectorAll('.option'),
feedback: document.getElementById('feedback'),
feedbackText: document.getElementById('feedback-text'),
startButton: document.getElementById('start-button'),
resetButton: document.getElementById('reset-button'),
nextSceneButton: document.getElementById('next-scene-button')
};
}
// 初始化游戏
function initGame() {
resetGameState();
loadScene(gameState.currentSceneIndex);
updateProgress();
}
// 重置游戏状态
function resetGameState() {
gameState = {
currentSceneIndex: 0,
currentDialogIndex: 0,
score: 0,
totalQuestions: 0,
correctAnswers: 0
};
}
// 加载场景
function loadScene(sceneIndex) {
if (sceneIndex >= englishData.scenes.length) {
showGameComplete();
return;
}
const scene = englishData.scenes[sceneIndex];
// 更新场景信息
elements.sceneTitle.textContent = scene.title;
elements.sceneDescription.textContent = scene.description;
// 加载场景图片
// 简化的图片加载逻辑优先使用场景ID作为图片名称
let imagePath = scene.image;
// 确保图片元素存在
if (!elements.sceneImage) {
console.error('场景图片元素不存在');
return;
}
// 重置图片状态
elements.sceneImage.src = '';
elements.sceneImage.alt = scene.title + '场景插图';
elements.sceneImage.style.display = 'none';
// 如果没有指定图片路径则使用场景ID作为图片名称自动查找
if (!imagePath) {
// 简单的命名规则images/[场景ID].[扩展名] 或 images/[场景标题拼音].[扩展名]
const possibleExtensions = ['.jpg', '.jpeg', '.png', '.gif', '.webp', '.bmp', '.svg'];
const baseNameId = scene.id.toString();
// 将场景标题转换为拼音风格的文件名(去掉空格和特殊字符,转为小写)
const baseNameTitle = scene.title
.replace(/[^\u4e00-\u9fa5a-zA-Z0-9]/g, '') // 保留中英文数字
.toLowerCase();
// 所有可能的图片路径优先ID命名然后标题拼音命名
const allPossiblePaths = [
// 优先使用ID命名
...possibleExtensions.map(ext => `images/${baseNameId}${ext}`),
// 也支持标题拼音命名
...possibleExtensions.map(ext => `images/${baseNameTitle}${ext}`)
];
console.log('尝试查找图片路径:', allPossiblePaths);
// 递归检查图片是否存在
function checkImage(index) {
if (index >= allPossiblePaths.length) {
console.log('未找到任何图片');
return;
}
const potentialPath = allPossiblePaths[index];
console.log('尝试加载图片:', potentialPath);
const img = new Image();
img.onload = function() {
console.log('图片加载成功:', potentialPath);
// 图片存在,设置路径并显示
elements.sceneImage.src = potentialPath;
elements.sceneImage.style.display = 'block';
};
img.onerror = function() {
console.log('图片加载失败:', potentialPath);
// 图片不存在,检查下一个
checkImage(index + 1);
};
img.src = potentialPath;
}
// 开始检查
checkImage(0);
} else {
console.log('使用指定的图片路径:', imagePath);
// 使用指定的图片路径
elements.sceneImage.src = imagePath;
elements.sceneImage.onload = function() {
elements.sceneImage.style.display = 'block';
};
elements.sceneImage.onerror = function() {
console.error('指定的图片路径加载失败:', imagePath);
elements.sceneImage.style.display = 'none';
};
}
// 清空对话区域
elements.conversation.innerHTML = '';
// 重置对话索引
gameState.currentDialogIndex = 0;
// 显示第一个对话
showNextDialog();
// 更新进度
updateProgress();
// 隐藏下一场景按钮
elements.nextSceneButton.disabled = true;
}
// 显示下一个对话
function showNextDialog() {
const scene = englishData.scenes[gameState.currentSceneIndex];
const conversation = scene.conversation;
if (gameState.currentDialogIndex >= conversation.length) {
// 当前场景对话结束
if (gameState.currentSceneIndex < englishData.scenes.length - 1) {
elements.nextSceneButton.disabled = false;
}
return;
}
const dialog = conversation[gameState.currentDialogIndex];
if (dialog.type === 'user_question') {
// 显示选择题
showQuestion(dialog);
} else {
// 显示普通对话
addMessage(dialog);
// 自动显示下一个对话
gameState.currentDialogIndex++;
setTimeout(showNextDialog, 1000);
}
}
// 添加对话消息
function addMessage(dialog) {
const messageDiv = document.createElement('div');
messageDiv.className = `message ${dialog.type}`;
const speakerSpan = document.createElement('span');
speakerSpan.className = 'speaker';
speakerSpan.textContent = dialog.speaker + ':';
const textSpan = document.createElement('span');
textSpan.className = 'text';
textSpan.textContent = dialog.text;
messageDiv.appendChild(speakerSpan);
messageDiv.appendChild(textSpan);
elements.conversation.appendChild(messageDiv);
// 滚动到底部
elements.conversation.scrollTop = elements.conversation.scrollHeight;
}
// 显示选择题
function showQuestion(dialog) {
elements.questionText.textContent = dialog.question;
// 复制选项数组并打乱顺序
const originalOptions = [...dialog.options];
const shuffledOptions = [...originalOptions];
// 使用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 correctAnswerText = originalOptions[dialog.correctAnswer];
const newCorrectIndex = shuffledOptions.indexOf(correctAnswerText);
// 保存原始选项和新的正确答案索引到对话对象中,供后续检查使用
dialog.originalOptions = originalOptions;
dialog.shuffledOptions = shuffledOptions;
dialog.shuffledCorrectAnswer = newCorrectIndex;
// 设置打乱后的选项
elements.options.forEach((option, index) => {
option.textContent = shuffledOptions[index];
option.disabled = false;
option.classList.remove('selected', 'correct', 'incorrect');
});
// 显示选择题区域
elements.questionArea.style.display = 'block';
elements.feedback.style.display = 'none';
}
// 处理选项选择
function handleOptionSelect(selectedOptionIndex) {
const scene = englishData.scenes[gameState.currentSceneIndex];
const dialog = scene.conversation[gameState.currentDialogIndex];
// 使用打乱后的正确答案索引
const correctAnswerIndex = dialog.shuffledCorrectAnswer !== undefined ? dialog.shuffledCorrectAnswer : dialog.correctAnswer;
// 禁用所有选项
elements.options.forEach(option => {
option.disabled = true;
});
// 标记选择的选项
const selectedOption = elements.options[selectedOptionIndex];
selectedOption.classList.add('selected');
// 检查答案
gameState.totalQuestions++;
let isCorrect = false;
if (selectedOptionIndex === correctAnswerIndex) {
// 正确答案
gameState.score += 10;
gameState.correctAnswers++;
selectedOption.classList.add('correct');
showFeedback(true, dialog);
isCorrect = true;
} else {
// 错误答案
selectedOption.classList.add('incorrect');
elements.options[correctAnswerIndex].classList.add('correct');
showFeedback(false, dialog);
}
// 更新得分和进度
updateProgress();
// 添加用户选择的对话
addUserChoiceToConversation(dialog, selectedOptionIndex, isCorrect);
// 延迟后显示下一个对话
setTimeout(() => {
gameState.currentDialogIndex++;
elements.questionArea.style.display = 'none';
elements.feedback.style.display = 'none';
showNextDialog();
}, 3000);
}
// 添加用户选择到对话
function addUserChoiceToConversation(dialog, selectedIndex, isCorrect) {
const userMessage = {
speaker: dialog.speaker,
text: dialog.options[selectedIndex],
type: 'user'
};
addMessage(userMessage);
}
// 显示反馈
function showFeedback(isCorrect, dialog) {
const feedbackTextElement = elements.feedbackText;
if (isCorrect) {
// 正确答案
feedbackTextElement.textContent = '正确! 很好的回答。';
feedbackTextElement.className = 'correct';
elements.feedback.style.borderColor = '#4CAF50';
elements.feedback.style.backgroundColor = '#e8f5e8';
} else {
// 错误答案
// 根据是否有打乱后的选项来选择使用哪个数组
const correctAnswer = dialog.shuffledOptions && dialog.shuffledCorrectAnswer !== undefined
? dialog.shuffledOptions[dialog.shuffledCorrectAnswer]
: dialog.options[dialog.correctAnswer];
feedbackTextElement.textContent = `不正确。正确答案是: ${correctAnswer}`;
feedbackTextElement.className = 'incorrect';
elements.feedback.style.borderColor = '#f44336';
elements.feedback.style.backgroundColor = '#ffebee';
}
elements.feedback.style.display = 'block';
}
// 更新进度
function updateProgress() {
elements.scoreElement.textContent = `得分: ${gameState.score}`;
elements.progressElement.textContent = `进度: ${gameState.currentSceneIndex + 1}/${englishData.scenes.length}`;
}
// 显示游戏完成信息
function showGameComplete() {
elements.conversation.innerHTML = '';
elements.questionArea.style.display = 'none';
const completeMessage = document.createElement('div');
completeMessage.className = 'message other';
completeMessage.innerHTML = `
<span class="speaker">学习完成:</span>
<span class="text">
恭喜您完成了所有场景的学习<br>
总得分: ${gameState.score}<br>
正确题目: ${gameState.correctAnswers}/${gameState.totalQuestions}
</span>
`;
elements.conversation.appendChild(completeMessage);
elements.nextSceneButton.disabled = true;
}
// 设置事件监听器
function setupEventListeners() {
// 选项按钮点击事件
elements.options.forEach((option, index) => {
option.addEventListener('click', () => {
handleOptionSelect(index);
});
});
// 开始按钮点击事件
elements.startButton.addEventListener('click', () => {
initGame();
elements.startButton.style.display = 'none';
});
// 重置按钮点击事件
elements.resetButton.addEventListener('click', () => {
initGame();
elements.startButton.style.display = 'none';
});
// 下一场景按钮点击事件
elements.nextSceneButton.addEventListener('click', () => {
gameState.currentSceneIndex++;
loadScene(gameState.currentSceneIndex);
});
}
// 页面加载完成后初始化游戏
document.addEventListener('DOMContentLoaded', () => {
// 获取DOM元素
getDomElements();
2026-01-09 01:01:23 +08:00
// 设置事件监听器(只调用一次)
setupEventListeners();
2026-01-08 21:14:46 +08:00
// 确保englishData已加载
if (typeof englishData !== 'undefined') {
initGame();
elements.startButton.style.display = 'block';
} else {
console.error('英语学习数据未加载');
}
});