zylyzghc/script.js
2026-01-09 01:01:23 +08:00

401 lines
13 KiB
JavaScript
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.

// 英语学习网页主脚本
// 游戏状态
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();
// 设置事件监听器(只调用一次)
setupEventListeners();
// 确保englishData已加载
if (typeof englishData !== 'undefined') {
initGame();
elements.startButton.style.display = 'block';
} else {
console.error('英语学习数据未加载');
}
});