JavaScript测验选项洗牌重复问题求助(附代码)
解决测验应用选项重复显示及判分错误问题
问题根源
- 选项重复:当前代码在循环输出选项时,每次都从原
answer数组随机选取元素,未排除已选选项,导致同一选项可能被重复选中多次。 - 隐藏判分错误:原代码中
correct字段是基于原选项数组的1-based索引,洗牌后正确答案位置改变,原correct值无法匹配新的选项顺序,会导致判分逻辑失效。
解决方案
使用Fisher-Yates洗牌算法(业界标准的无偏洗牌方法)对选项数组进行洗牌,同时跟踪正确答案在洗牌后的位置,保证选项不重复且判分逻辑正确。
修正后的完整代码
const questions = [{ question: "What is the name of Ellie's mom?", answer: ["Jessica", "Monica", "Anna", "Tess"], correct: "3", }, { question: "Around how old is Joel in The Last of Us Part II?", answer: ["40s", "50s", "60s", "70s"], correct: "2", }, { question: "What is Manny's rank in the WLF?", answer: ["Sergeant", "Captain", "Lieutenant", "Corporal"], correct: "3", }, { question: "What item does Ellie keep of Sam's that can be seen in her room at the start of The Last of Us Part II?", answer: ["PS3", "Toy robot", "Cassette player", "Animals of the Past book"], correct: "2", }, { question: "Which game does NOT get referenced in The Last of US Part II?", answer: ["Deus Ex", "God of War", "Jak and Daxter", "Crash Bandicoot"], correct: "2", } ]; /* Getting elements from the DOM */ let headerContainer = document.getElementById("header"); let listContainer = document.getElementById("list"); let submitBtn = document.getElementById("submit"); let startBtn = document.getElementById("start"); let quiz = document.getElementById("quiz"); let score = 0; let questionIndex = 0; startBtn.onclick = function () { startBtn.classList.add("hidden"); quiz.classList.remove("hidden"); document.getElementById("description").classList.add("hidden"); }; function clearPage() { headerContainer.innerHTML = ""; listContainer.innerHTML = ""; } // Fisher-Yates 洗牌算法,返回新数组,不修改原数组 function shuffleArray(array) { const newArray = [...array]; let currentIndex = newArray.length, randomIndex; while (currentIndex !== 0) { randomIndex = Math.floor(Math.random() * currentIndex); currentIndex--; [newArray[currentIndex], newArray[randomIndex]] = [newArray[randomIndex], newArray[currentIndex]]; } return newArray; } clearPage(); showQuestion(); submitBtn.onclick = checkAnswer; /*A function to show questions*/ function showQuestion() { /*Show a question*/ let headerTemplate = `<h2 class="title">%title%</h2>`; let title = headerTemplate.replace('%title%', questions[questionIndex].question); headerContainer.innerHTML = title; /* 洗牌选项数组,不修改原数组 */ const originalAnswers = questions[questionIndex].answer; const shuffledAnswers = shuffleArray(originalAnswers); // 计算正确答案在洗牌后的数组中的1-based位置 const correctAnswer = originalAnswers[questions[questionIndex].correct - 1]; const correctValue = (shuffledAnswers.indexOf(correctAnswer) + 1).toString(); // 存储当前题目的正确value,供判分使用 questions[questionIndex].currentCorrect = correctValue; /*Show answers*/ let answerNumber = 1; for (const answer of shuffledAnswers) { const questionTemplate = `<li> <label> <input value="%number%" type="radio" class="answer" name="answer"> <span>%answer%</span> </label> </li>`; let answerText = questionTemplate.replace('%answer%', answer).replace("%number%", answerNumber); listContainer.innerHTML += answerText; answerNumber++; } let progress = `<p>${questionIndex+1} out of ${questions.length}</p>`; document.getElementById("progress").innerHTML = progress; let scoreBoard = `<p>Score: ${score} out of ${questions.length}</p>`; document.getElementById("score").innerHTML = scoreBoard; } // 判分函数 function checkAnswer() { const selectedOption = document.querySelector('input[name="answer"]:checked'); if (!selectedOption) { alert("请选择一个选项"); return; } if (selectedOption.value === questions[questionIndex].currentCorrect) { score++; } questionIndex++; if (questionIndex < questions.length) { clearPage(); showQuestion(); } else { // 显示最终结果 clearPage(); headerContainer.innerHTML = `<h2>测验结束</h2><p>你的得分:${score}/${questions.length}</p>`; submitBtn.classList.add("hidden"); } }
关键说明
- Fisher-Yates洗牌:通过交换数组元素实现无重复随机排列,且不会修改原数组,避免影响其他题目。
- 正确答案跟踪:通过原
correct值定位正确答案文本,再在洗牌后的数组中找到其位置,生成新的currentCorrect值,确保判分逻辑与洗牌后的选项匹配。 - 避免重复:直接遍历洗牌后的数组输出选项,每个选项只会出现一次。
内容的提问来源于stack exchange,提问作者pozhara
相关产品推荐
相关产品推荐

