如何为JavaScript测验添加选项洗牌功能并保持答案正确性
解决方案
核心要解决的问题是让每个选项携带「是否正确」的标记,而非依赖它的原始位置——如果你的选项之前是纯文本数组+单独的正确答案索引,洗牌后索引失效就会导致判定错误。以下是具体实现步骤:
1. 重构问题数据结构
把每个问题的选项改成包含文本和正确标记的对象数组,示例:
const quizQuestions = [ { question: "JavaScript的创始人是谁?", options: [ { text: "Brendan Eich", isCorrect: true }, { text: "Guido van Rossum", isCorrect: false }, { text: "James Gosling", isCorrect: false }, { text: "Tim Berners-Lee", isCorrect: false } ] }, // 更多问题... ];
2. 实现Fisher-Yates洗牌函数
这是公平性最高的原地洗牌算法:
function shuffleOptions(options) { let currentIndex = options.length, randomIndex; // 遍历未洗牌的元素 while (currentIndex !== 0) { // 随机选取未洗牌元素的索引 randomIndex = Math.floor(Math.random() * currentIndex); currentIndex--; // 交换当前元素与随机元素 [options[currentIndex], options[randomIndex]] = [options[randomIndex], options[currentIndex]]; } return options; }
3. 洗牌并渲染问题
加载每个问题时,先对该问题的选项洗牌(注意复制原数组避免修改原始数据),再渲染到页面:
function loadQuestion(questionIndex) { const currentQuestion = quizQuestions[questionIndex]; // 复制原选项数组后洗牌,防止修改原始数据 const shuffledOptions = shuffleOptions([...currentQuestion.options]); // 渲染题目文本 document.getElementById('question-text').textContent = currentQuestion.question; // 渲染选项列表 const optionsContainer = document.getElementById('options-container'); optionsContainer.innerHTML = ''; shuffledOptions.forEach(option => { const optionElement = document.createElement('div'); optionElement.className = 'option'; optionElement.textContent = option.text; // 绑定点击事件,直接传递当前选项的正确标记 optionElement.addEventListener('click', () => checkAnswer(option.isCorrect)); optionsContainer.appendChild(optionElement); }); }
4. 答案判定逻辑
直接通过选项的isCorrect属性判断,不再依赖索引:
function checkAnswer(isCorrect) { if (isCorrect) { alert('回答正确!'); // 这里添加下一题、得分统计等逻辑 } else { alert('回答错误,请再试试!'); } }
常见问题排查
- 如果出现后续问题选项重复洗牌的情况,检查是否在洗牌时直接修改了原数组——必须用
[...options]或options.slice()复制数组后再操作。 - 若点击选项时判定逻辑出错,确认事件绑定的是当前选项的
isCorrect属性,避免闭包导致的变量污染。
内容的提问来源于stack exchange,提问作者Timmyontech
相关产品推荐
相关产品推荐

