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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 05:45:58