You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript测验选项洗牌重复问题求助(附代码)

解决测验应用选项重复显示及判分错误问题

问题根源

  1. 选项重复:当前代码在循环输出选项时,每次都从原answer数组随机选取元素,未排除已选选项,导致同一选项可能被重复选中多次。
  2. 隐藏判分错误:原代码中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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 03:16:25