如何在 HTML/JavaScript 测验应用中实现题目随机化

本文教你用 javascript 为测验应用添加题目随机显示功能,通过生成不重复的随机索引从题库中抽取题目,并解释其工作原理与关键注意事项。

在构建一个专业级的在线测验应用时,确保每次练习都呈现不同顺序的题目,不仅能提升学习效果,还能防止记忆位置而非内容。你当前的代码已具备完整结构(题库分离、DOM 渲染、选项渲染),只需将固定索引 index 替换为可控的随机索引即可实现题目乱序——但需注意:真正的“随机”不等于“重复”,尤其在单次测验中,我们通常希望每道题仅出现一次

✅ 正确做法:使用「洗牌 + 迭代」或「带去重的随机索引生成」

虽然答案中提供的 getRandomIndexFromArray 函数看似可行,但它存在逻辑缺陷:while 循环内重新赋值 randomIndex

时未更新判断条件,且未处理所有题目已抽完的边界情况(可能导致无限循环)。更可靠、简洁且符合工程实践的方式是——先打乱题库数组顺序,再按顺序逐题展示

✅ 推荐方案:Fisher-Yates 洗牌算法(高效 & 真随机)

在加载题库后、开始答题前,对 questions 数组进行原地随机排序:

// 在 script.js 开头或初始化阶段调用
function shuffleArray(arr) {
  for (let i = arr.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [arr[i], arr[j]] = [arr[j], arr[i]]; // ES6 解构交换
  }
  return arr;
}

// 假设 questions 已从 questions.js 加载完成
const shuffledQuestions = shuffleArray([...questions]); // 浅拷贝避免污染原始数据
let currentQuestionIndex = 0;

随后,在显示题目时,不再依赖外部 index 变量,而是使用 currentQuestionIndex 从 shuffledQuestions 中取题:

function showQuestion() {
  if (currentQuestionIndex >= shuffledQuestions.length) {
    alert("测验结束!");
    return;
  }

  const q = shuffledQuestions[currentQuestionIndex];
  questionText.textContent = q.question;

  const optionTag = `
    ${q.options[0]}
    ${q.options[1]}
    ${q.options[2]}
    ${q.options[3]}
  `;
  document.querySelector('.options').innerHTML = optionTag;
}

// 启动测验时调用
showQuestion();
? 为什么这比“边抽边查重”更好? 时间复杂度稳定 O(n),无死循环风险; 保证所有题目恰好出现一次,且顺序完全随机; 符合人类认知习惯(如考试卷本身是固定题序,只是题序被预先打乱); 易于扩展:支持“只抽 10 题”可改为 shuffleArray(questions).slice(0, 10)。

⚠️ 注意事项

  • ❌ 不要直接修改 questions.js 中的原始数组(如全局 questions = shuffleArray(questions)),否则多次重启测验会复用同一乱序结果;应每次新建副本。
  • ✅ 若需支持“重新测验”,只需再次调用 shuffleArray([...questions]) 并重置 currentQuestionIndex = 0。
  • ? 确保 questions.js 是通过
  • ? 如需保留题号显示(如“第 7 题”),可改用 shuffledQuestions[currentQuestionIndex].numb,但注意它反映的是原始编号,非当前顺序。

通过这一改进,你的工作培训测验将真正具备专业性与可复用性——每一次练习,都是全新的挑战。