JavaScript Trivia游戏点击正确答案按钮却显示错误结果的问题
问题描述
我用原生JS和Bootstrap开发答题游戏,从API获取题目,通过生成不重复随机数组打乱答案按钮的显示顺序。添加nextQuestion函数实现题目切换后,点击正确答案按钮时不会显示“Correct!”,反而随机某个按钮会显示“Incorrect”。之前通过刷新页面生成新题目时没有这个问题。试过将randomArray设为全局变量、在nextQuestion里重置它,也打印过数组确认变化,发现大多时候上一题正确答案的位置会显示错误提示。
问题根源
- 事件监听器重复绑定:每次调用
displayQuestion都会给按钮添加新的点击事件,同一个按钮会被绑定多个不同的处理函数。点击按钮时会执行所有绑定的函数,而此时randomArray已经被新题的数据覆盖,导致用新数组的位置去定位按钮,错误提示出现在不正确的位置。 - 全局变量被覆盖:
randomArray是全局变量,新题加载时会被重新赋值,但之前的点击处理函数仍在引用这个变量,导致处理逻辑使用的是新题的位置数组,而非当前点击题目对应的数组。
修复方案
核心改进思路
- 页面加载时一次性给所有按钮绑定通用点击处理函数,避免重复绑定
- 保存当前题目的正确答案按钮ID,不再依赖易被覆盖的全局数组
修改后的完整代码
Main.js
const api_url = 'https://opentdb.com/api.php?amount=1&category=9&type=multiple&encode=url3986'; let score = 0; let buttonClicked = false; const delay = 2000; let currentCorrectButtonId = ''; // 保存当前正确答案的按钮ID // 页面初始化时绑定所有按钮的点击事件 document.getElementById('answer1').addEventListener('click', handleAnswerClick); document.getElementById('answer2').addEventListener('click', handleAnswerClick); document.getElementById('answer3').addEventListener('click', handleAnswerClick); document.getElementById('answer4').addEventListener('click', handleAnswerClick); async function getQuestion() { try { const response = await fetch(api_url); const data = await response.json(); const { results } = data; displayQuestion(results); } catch (error) { console.log(error); } } function displayQuestion(results) { const question = decodeURIComponent(results[0].question); const correctAnswer = decodeURIComponent(results[0].correct_answer); const incorrectAnswers = results[0].incorrect_answers.map(ans => decodeURIComponent(ans)); // 合并答案并打乱顺序 const allAnswers = [correctAnswer, ...incorrectAnswers]; const buttonIds = ['answer1', 'answer2', 'answer3', 'answer4']; shuffleArray(buttonIds); // 渲染题目 document.getElementById('question').textContent = question; // 给按钮赋值并记录正确答案位置 buttonIds.forEach((id, index) => { const button = document.getElementById(id); button.textContent = allAnswers[index]; if (allAnswers[index] === correctAnswer) { currentCorrectButtonId = id; } // 重置按钮样式 button.className = 'btn btn-primary btn-sm'; }); } // 统一处理所有按钮点击 function handleAnswerClick(e) { if (buttonClicked) return; buttonClicked = true; const clickedButton = e.target; if (clickedButton.id === currentCorrectButtonId) { // 正确答案逻辑 clickedButton.innerHTML = "Correct!"; clickedButton.className = 'btn btn-success btn-sm'; score++; updateScore(); } else { // 错误答案逻辑,同时高亮正确答案 clickedButton.innerHTML = "Incorrect!"; clickedButton.className = 'btn btn-danger btn-sm'; const correctBtn = document.getElementById(currentCorrectButtonId); correctBtn.innerHTML = "Correct!"; correctBtn.className = 'btn btn-success btn-sm'; } setTimeout(() => { nextQuestion(); buttonClicked = false; }, delay); } function updateScore() { const scoreElement = document.getElementById('score'); scoreElement.textContent = `Score: ${score}`; } function nextQuestion() { document.getElementById('question').textContent = ''; // 重置所有按钮状态 ['answer1', 'answer2', 'answer3', 'answer4'].forEach(id => { const button = document.getElementById(id); button.textContent = ''; button.className = 'btn btn-primary btn-sm'; }); getQuestion(); } // Fisher-Yates标准洗牌算法 function shuffleArray(array) { for (let i = array.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [array[i], array[j]] = [array[j], array[i]]; } } getQuestion();
game.html(无需修改)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Trivia Game</title> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-gH2yIJqKdNHPEq0n4Mqa/HGKIhSkIHeL5AyhkYV8i59U5AR6csBvApHHNl/vI1Bx" crossorigin="anonymous"> <link href="/css/style.css" rel="stylesheet"> </head> <body> <div id="container"> <div class="text-center font-weight-bold col-8 mx-auto"> <span id="question"></span> </div> <div class="d-grid gap-2 col-4 mx-auto"> <button type="button" class="btn btn-primary btn-sm p-1" id="answer1"></button> <button type="button" class="btn btn-primary btn-sm" id="answer2"></button> <button type="button" class="btn btn-primary btn-sm" id="answer3"></button> <button type="button" class="btn btn-primary btn-sm" id="answer4"></button> <div class="text-center" id="score">Score: 0</div> </div> </div> <script src="main.js"></script> </body> </html>
关键优化点
- 避免重复绑定事件,解决多次执行处理函数的问题
- 用独立变量保存当前正确按钮ID,彻底避免全局数组被覆盖的干扰
- 使用标准洗牌算法,保证答案顺序随机的可靠性
- 错误点击时同步高亮正确答案,优化用户体验
内容的提问来源于stack exchange,提问作者Darren Revell
相关产品推荐
相关产品推荐

