Java测验选项洗牌后正确答案索引混乱问题求助
Java测验Demo选项洗牌后答案判定错误问题解决
问题描述
我正在完成一项学校作业,开发一个Java测验Demo。但在对题目选项进行洗牌后,正确答案的索引出现混乱,输入正确选项的编号却被判定为错误,无法解决该问题。
相关代码
洗牌方法
private String[] shuffleOptions(String[] options, int answer) { Random ran = new Random(); // 洗牌前的正确答案文本 String answerValue = options[answer]; // 随机打乱选项 for (int i = options.length - 1; i > 0; i--) { int index = ran.nextInt(i + 1); String temp = options[index]; options[index] = options[i]; options[i] = temp; } // 查找洗牌后的正确答案索引 for (int i = 0; i < options.length; i++) { if (options[i].equals(answerValue)) { answerTemp = i; } } return options; }
完整Quiz类代码
import java.util.Random; import java.util.Scanner; public class Quiz { private String name; private Question[] questions; private int capacity; private int size; private int score; private int answerTemp; Quiz(){ this.name = "Quiz" + String.valueOf(Math.random()*1000); this.questions = new Question[5]; this.capacity = 5; this.size = 0; this.score = 0; this.answerTemp = 0; } private void increaseCapacity() { // 创建容量翻倍的新题目数组 capacity *= 2; Question[] doubleQuestions = new Question[capacity]; if (size > 0) { System.arraycopy(questions, 0, doubleQuestions, 0, size); } questions = doubleQuestions; } public void addQuestion(Question question) { if (size >= capacity) { // 达到题目数组最大容量 increaseCapacity(); } questions[size++] = question; } private String[] shuffleOptions(String[] options, int answer) { Random ran = new Random(); // 洗牌前的正确答案文本 String answerValue = options[answer]; // 随机打乱选项 for (int i = options.length - 1; i > 0; i--) { int index = ran.nextInt(i + 1); String temp = options[index]; options[index] = options[i]; options[i] = temp; } // 查找洗牌后的正确答案索引 for (int i = 0; i < options.length; i++) { if (options[i].equals(answerValue)) { answerTemp = i; } } return options; } private String finalScore() { // 返回百分比形式的最终得分 int finalScore = (int) ((double) score / size * 100); return("FINAL SCORE: " + finalScore + "%" + "!"); } public void giveQuiz() { Scanner userInput = new Scanner(System.in); int userAnswer = 0; for (int i = 0; i < size; i++) { Question currentQuestion = questions[i]; System.out.println("Question " + (i + 1) + ") : " + currentQuestion.getQuestion()); String[] shuffledOptions = shuffleOptions(currentQuestion.getOptions(), currentQuestion.getAnswer()); currentQuestion.setAnswer(answerTemp); // 设置正确答案的索引 for (int x = 0; x < shuffledOptions.length; x++) { // 打印洗牌后的选项 System.out.println("(" + (x + 1) + ") " + shuffledOptions[x]); } System.out.println("\n Type Answer (1-4): "); userAnswer = userInput.nextInt(); if (userAnswer == currentQuestion.getAnswer()) { // 检查答案是否正确 System.out.println("\nCORRECT ANSWER"); score++; } else { System.out.println("\nWRONG ANSWER"); } } System.out.println(finalScore()); userInput.close(); } //end of giveQuiz }
问题原因
- 编号与索引不匹配:用户输入的是1-4的选项编号(1-based),但程序中
currentQuestion.getAnswer()存储的是数组索引(0-based),直接用userAnswer == currentQuestion.getAnswer()比较会导致逻辑错误,比如用户选编号1(对应索引0),程序拿1和索引0对比,自然判定错误。 - 原数组被修改(潜在问题):
shuffleOptions方法直接操作传入的options数组(Java数组是引用类型),会修改Question对象中原有的选项数组,若后续复用题目会导致数据异常。 - 成员变量复用风险:
answerTemp作为类成员变量,连续处理题目时可能被覆盖,虽单线程下影响小,但设计不够严谨。
解决方案
核心修复:匹配编号与索引
将用户输入的1-based编号转换为0-based索引,再和正确答案索引比较;或者在设置正确答案时直接存储1-based编号。
优化后代码示例
修改洗牌方法(避免修改原数组,返回正确索引)
// 洗牌方法:传入原数组,输出洗牌后的数组和正确答案索引(0-based) private int shuffleOptions(String[] originalOptions, String[] shuffledOptions) { Random ran = new Random(); // 复制原数组,避免修改Question对象的原始数据 System.arraycopy(originalOptions, 0, shuffledOptions, 0, originalOptions.length); // 获取原正确答案文本 String answerValue = originalOptions[questions[i].getAnswer()]; // 执行洗牌 for (int i = shuffledOptions.length - 1; i > 0; i--) { int index = ran.nextInt(i + 1); String temp = shuffledOptions[index]; shuffledOptions[index] = shuffledOptions[i]; shuffledOptions[i] = temp; } // 查找洗牌后的正确索引 for (int i = 0; i < shuffledOptions.length; i++) { if (shuffledOptions[i].equals(answerValue)) { return i; } } return -1; // 理论上不会触发 }
修改giveQuiz方法(适配索引转换)
public void giveQuiz() { Scanner userInput = new Scanner(System.in); int userAnswer = 0; for (int i = 0; i < size; i++) { Question currentQuestion = questions[i]; System.out.println("Question " + (i + 1) + ") : " + currentQuestion.getQuestion()); String[] originalOptions = currentQuestion.getOptions(); String[] shuffledOptions = new String[originalOptions.length]; // 获取洗牌后的正确答案索引(0-based) int correctIndex = shuffleOptions(originalOptions, shuffledOptions); // 打印1-based编号的选项 for (int x = 0; x < shuffledOptions.length; x++) { System.out.println("(" + (x + 1) + ") " + shuffledOptions[x]); } System.out.println("\nType Answer (1-4): "); userAnswer = userInput.nextInt(); // 将用户输入的1-based编号转为0-based索引,再与正确索引比较 if (userAnswer - 1 == correctIndex) { System.out.println("\nCORRECT ANSWER"); score++; } else { System.out.println("\nWRONG ANSWER"); } } System.out.println(finalScore()); userInput.close(); }
替代方案(直接存储1-based编号)
如果不想转换索引,可以在shuffleOptions中找到正确索引后,设置为1-based编号:
// 在shuffleOptions方法末尾 answerTemp = i + 1; // 转为1-based编号
然后在giveQuiz中直接比较:
if (userAnswer == currentQuestion.getAnswer()) { ... }
总结
最关键的错误是1-based编号和0-based索引的直接对比,修正这个逻辑即可解决答案判定错误的问题。同时复制数组操作可以避免污染原始题目数据,提升代码健壮性。
内容的提问来源于stack exchange,提问作者LMjava
相关产品推荐
相关产品推荐

