多题库随机抽题组卷的JavaScript实现难题求助
在线考试系统随机抽题与功能实现方案
先解决你当前遇到的两个核心问题,再帮你实现后续需要的功能:
一、解决现有抽题问题
1. 修复randsplice导致的二维数组扁平化问题
你的randsplice方法返回的是splice的结果——一个包含被删除元素的数组,而不是单个题目元素。这会导致你push到newArray里的是嵌套数组,后续处理时容易扁平化,把题目和选项混为一谈。
修改randsplice方法,直接返回被删除的单个题目元素:
Array.prototype.randsplice = function() { var ri = Math.floor(Math.random() * this.length); // 取splice返回数组的第一个元素(因为我们只删了1个) var rs = this.splice(ri, 1)[0]; return rs; }
2. 解决randval重复抽题的问题
randval只是随机读取元素不删除,自然会重复。更优雅的方式是先洗牌再截取前N个,既不会重复,也不会修改原题库数组(方便后续复用):
// 给数组添加随机抽取n个不重复元素的方法 Array.prototype.sample = function(n) { // 先复制原数组,避免修改原题库 const copy = [...this]; // 用你已有的shuffle方法打乱 copy.shuffle(); // 取前n个元素 return copy.slice(0, n); }
然后简化你的抽题逻辑,不用那些冗余的newArray和myFunction:
// 每个题库要抽取的题目数量 const pool1Count = 2; const pool2Count = 2; // 从两个题库抽题并合并 const selectedQuestions = [ ...questions.sample(pool1Count), ...questions2.sample(pool2Count) ]; // 混排所有选中的题目 selectedQuestions.shuffle();
二、实现你需要的额外功能
1. 可开关的选项乱序(数值类自动排序)
需要先判断选项是否为数值,再决定是乱序还是排序,同时要同步更新正确答案的字母标识(因为选项位置变了):
// 判断选项是否全为数值 function areOptionsNumeric(question) { // 题目结构是[题干, 选项A, 选项B, 选项C, 正确答案],取选项部分 const options = question.slice(1, 4); return options.every(opt => !isNaN(parseFloat(opt)) && isFinite(opt)); } // 处理选项排序/乱序的核心函数 function handleOptions(question, enableShuffle) { if (!enableShuffle) return question; const [title, optA, optB, optC, correctLetter] = question; const options = [optA, optB, optC]; // 获取正确选项的实际内容 const correctValue = question[["A","B","C"].indexOf(correctLetter) + 1]; let processedOptions; if (areOptionsNumeric(question)) { // 数值类选项从小到大排序 processedOptions = [...options].sort((a, b) => parseFloat(a) - parseFloat(b)); } else { // 非数值类选项乱序 processedOptions = [...options].shuffle(); } // 重新映射正确答案的字母 const newCorrectIndex = processedOptions.findIndex(opt => opt === correctValue); const newCorrectLetter = ["A","B","C"][newCorrectIndex]; return [title, ...processedOptions, newCorrectLetter]; } // 使用示例:开启选项乱序 const enableOptionShuffle = true; const finalQuestions = selectedQuestions.map(q => handleOptions(q, enableOptionShuffle));
2. 错题补救页面
需要在答题过程中记录错题,考试结束后渲染错题列表,支持重新作答:
// 存储错题的数组,包含题目和用户的错误答案 const wrongQuestions = []; // 检查答案的函数,同时记录错题 function checkUserAnswer(question, userAnswer) { const correctAnswer = question[4]; if (userAnswer === correctAnswer) { correct++; return true; } else { wrongQuestions.push({ question: [...question], // 复制题目避免后续修改影响 userAnswer: userAnswer }); return false; } } // 渲染错题补救页面的函数 function renderWrongPage() { if (wrongQuestions.length === 0) { alert("太棒了!你没有错题😎"); return; } let html = "<h3>错题补救</h3>"; wrongQuestions.forEach((item, index) => { const q = item.question; html += ` <div class="wrong-question"> <p>${index+1}. ${q[0]}</p> <p>选项:A.${q[1]} B.${q[2]} C.${q[3]}</p> <p>你的答案:${item.userAnswer} | 正确答案:${q[4]}</p> <button onclick="retryQuestion(${index})">重新作答</button> </div> `; }); document.getElementById("wrong-page").innerHTML = html; } // 重新作答的逻辑(示例) function retryQuestion(index) { const item = wrongQuestions[index]; // 这里可以弹出选择框让用户重新选答案,然后再次检查 const newAnswer = prompt("请输入你的答案(A/B/C):"); if (newAnswer === item.question[4]) { alert("答对了!"); // 可以从错题数组中移除该题 wrongQuestions.splice(index, 1); renderWrongPage(); } else { alert("还是错了,再想想!"); } }
3. 分数统计功能
直接根据正确题数和总题数计算,支持百分比或分值制:
// 计算分数(支持自定义每题分值) function calculateTotalScore(totalQuestions, correctAnswers, pointsPerQuestion = 1) { const totalPoints = totalQuestions * pointsPerQuestion; const earnedPoints = correctAnswers * pointsPerQuestion; const percentage = Math.round((earnedPoints / totalPoints) * 100); return { totalQuestions, correctAnswers, totalPoints, earnedPoints, percentage }; } // 使用示例 const score = calculateTotalScore(selectedQuestions.length, correct); alert(`考试结束!你的得分:${score.earnedPoints}/${score.totalPoints}(${score.percentage}%)`);
希望这些解决方案能帮你顺利完成项目,如果还有细节问题可以继续提问~
内容的提问来源于stack exchange,提问作者gwinnc




