【问题标题】:How to generate a list of distinct random numbers including a specific number in JAVA?如何在 JAVA 中生成包含特定数字的不同随机数列表?
【发布时间】:2017-06-06 23:22:48
【问题描述】:

好的,所以场景是,我想生成一个包含 4 个distinct 随机数的列表,这将代表一个测验应用程序的 4 个随机选择。 4 个随机选项之一将是正确答案,因此我们已经知道正确选项的索引。这个正确的索引或数字必须包含在随机数列表中。

例如: 假设我们有一个长度为 100 的 array,包含代表一个问题的 100 个选项的 string 值,而 index 的正确的选择是45。现在我们希望这个问题有 4 个随机选项,包括索引 45,因此索引列表将类似于 {2, 91, 45, 17}。此外,该列表不应包含重复的数字。

知道如何在 Java 中实现这一点吗?

【问题讨论】:

  • 您可以获得三个随机数,如stackoverflow.com/questions/363681/… 中所述,并将“正确索引”添加到您的可能答案数组中。为避免正确答案始终位于同一位置,您可以随机排列数组。
  • 生成 3 个最小为 0 和最大数组大小为 1 的随机数,并检查给定值是否已被选取。 3 因为你知道你的答案。我们以这种方式做了类似的事情。

标签: java random


【解决方案1】:

对于 Java 6 及更新版本:

final int maxNumber = 100;
final int numbersToGenerate = 4;
final int correctAnswer = 45;

Set<Integer> possibleAnswers = new HashSet<>();
Random random = new Random();

// add correct answer
possibleAnswers.add(correctAnswer);

// add as much random answers as needed, the usage of a set prevents duplicates
while(possibleAnswers.size() < numbersToGenerate) {
    possibleAnswers.add(random.nextInt(maxNumber));
}

// convert set to list and shuffle it
List<Integer> answers = new ArrayList<Integer>(possibleAnswers);
Collections.shuffle(answers, new Random(System.nanoTime()));

对于低于 6 的 Java 版本,您必须编写自己的 shuffle 方法,因为据我所知,Collections.shuffle 是在 Java 6 中引入的。

我最初建议使用 Java 8 的随机 api,但在我的想法中发现了一个错误。如果生成的随机数数组包含正确答案,它将不起作用。为了您的理解:

不工作!!!

final int minNumber = 1;
final int maxNumber = 100;
final int numbersToGenerate = 3;

final int[] ints = new Random().ints(minNumber, maxNumber)
.distinct().limit(numbersToGenerate).toArray();

List<Integer> possibleAnswers = asList(ints);
possibleAnswers.add(correctAnswerIndex);
Collections.shuffle(possibleAnswers, new Random(System.nanoTime()));

不工作!!!

【讨论】:

  • 根据您的回答,它适用于 Java 8。您需要描述您将在旧 Java 中做什么,在某些情况下,有正当理由使用旧 Java。此外,您需要概括,可能答案的数量不一定是恒定的。如您所见,您的答案有几个缺点,但这不是拒绝它的理由,因为它在有限的用例中很有帮助。
  • Anton 您的回答应该尽可能笼统。您永远不应该假设当前的读者和未来的读者都在使用 Java 8。您的解决方案适用于少数用例。如果适用于他们的用例数量有限,人们可以使用它。如果没有,那么他们需要别的东西。您需要编辑您的答案并使您的代码更通用,最好使用可变数量的可能响应和使用旧 Java 的查看器的解决方案。除非你这样做,否则你的答案是不完整的。
  • 你的答案假设元素的数量是100。它会打乱所有的项目,所以如果属性的数量变大并且操作在一个循环中重复多次,那么你的代码会很慢并且在多线程环境中它不会很好地扩展。答案根本没有解释,它只是复制了一个操作员无法理解的代码(这就是他问的原因),并且给用户留下了关于发生了什么的谜团。所以这个答案是从 1000 个伤口流血。
  • 哦,太好了。我从来不知道 Random 也绑定到流 api。今天学到了一些新东西
  • 嗨 Anton,我可能是错的,但我猜这段代码不会生成包含不同数字的随机数列表。它可能有重复的数字。
【解决方案2】:

这门课可以帮到你

public class RandomQuiz {

    //The number of possible answers
    private int size;
    //The number of possible indexes
    private int n;
    //The correct index
    private int correct;

    //Constructor
    public RandomQuiz(int size, int n, int correct) {
        this.size = size;
        this.n = n;
        this.correct = correct;
    }

    //Returns size number of shuffled random indexes
    public int[] getRandomIndexes() {
        //The result set
        int[] result = new int[size];
        //We start with the correct index in the first place, so random values will be entered starting from the second place
        int index = 1;
        //First thing's first
        result[0] = correct;
        Random random;
        while (index < size) {
            //We always decrease the number of seeds
            random = new Random(n - index);
            //Getting a random value
            int randomized = random.nextInt();
            //Ensuring the numbers are not duplicate
            for (int i = 0; i < index; i++) if (randomized >= result[i]) randomized++;
            result[index++] = randomized;
        }
        //Randomize where correct will be at the end:
        random = new Random(size);
        int newIndex = random.getNextInt();
        //If the new index of correct is bigger than 0
        //than swap it with the item located on newIndex
        if (newIndex > 0) {
            result[0] = result[newIndex];
            result[newIndex] = correct;
        }
        return result;
    }
}

编辑:

在与 Anton 的私人聊天中,他告诉我有些部分不清楚,即:

  • 为什么我减少了种子的数量
  • 为什么我在一个周期内增加了randomized

种子的数量减少了,因为我们最多可以使用任何数量。如果种子是 100,那么在选择第一个项目后,它会变成 99,依此类推。回答第二个问题:如果选择了 45,然后选择了至少 45 中的一个数字,那么我们需要在该数字上加 1 以弥补选择 45 时留下的空白。如果选择了一些数字,我们选择一个新数字,然后我们需要在该数字上加上它下面的空白数,即已经选择的较小或相等数字的数量以应对所有空白。

请注意,没有任何内容是个人的,如果其他人的正确答案也被否决,我会留下我留下的那种 cmets。我并不反对我的答案被否决,而是反对总体上对正确答案投反对票。

【讨论】:

  • 太复杂了,需要很多行代码。事实证明,错误的数量不是随着代码的复杂性而增加,而是随着代码的行数增加!
  • @Anton “复杂”不是拒绝投票的理由。否决票意味着答案没有帮助。所以,请告诉我我的回答如何没有帮助并提出改进建议。或者撤销你的反对票。
  • 嗯,在我看来,我们不应该只给出一个“有效”的答案,而且我们应该给出一个好的答案来帮助人们改进他们的编程。而在我看来,过于复杂的解决方案/答案对提高开发技能没有帮助。除此之外,我希望看到更多的解释,只是粘贴一个类。
  • @Anton,这个答案展示了算法,所以它正在提高读者的编程能力。对解决问题的答案投反对票是完全非法的。欢迎您的批评,但除非您能证明这个答案的缺点(例如一个错误),否则您在否决它时是不正确的。另外,我的答案在 cmets 中进行了解释(添加到“多行”),而不仅仅是您的答案中的复制粘贴。
  • @Anton 你说代码对你来说很复杂。你能告诉我哪个部分难以理解,以便我详细说明吗?我将是一位绅士,不会假设您投反对票的原因是为了提高您的答案被接受的机会。如果您的回答质量得到提高,我对您的回答被接受没有任何问题。然而,就目前情况而言,我的回答早先给出,它应该在许多环境中工作,它在 cmets 中有解释。你的答案缺乏所有这些品质,但你却否决了我的答案。
【解决方案3】:

我根据您的需要编写了一个完整的程序。但是,请看看我在做什么。只需一点上下文,这就是我创建的:

     // initialize a random object once.
     Random random = new Random();
     // the question
     String question = "With what letter does the name start of the new president of the USA?";
     // here are some basic answers
     String[] answers = new String[] {
      "a",
      "b",
      "c",
      "d",
      "e",
      "f",
      "g",
      "h",
      "i",
      "j",
      "k"
     };
     // you already know the correct index of the array above, in this case it's d
     int index = 3;
     // this array will contain four answers, including correct one!
     String[] four = new String[4];
     // get answer index, we will place correct value in that index
     int answerIndex = random.nextInt(four.length);
     // now lets pick 4 answers!
     for (int i = 0; i < four.length; i++) {
      // we are at the answer index!
      if (i == answerIndex) {
       four[i] = answers[index];
       continue;
      }
      int randomIndex = random.nextInt(answers.length);
      for (int j = 0; j < four.length; j++) {
       // we got duplicate here!
       if (answers[randomIndex].equals(four[j])) {
        randomIndex = random.nextInt(answers.length);
        // redo this current iteration
        j = j - 1;
       }
      }
      four[i] = answers[randomIndex];
     }

输出:

e, c, d, h
g, d, d, h
d, g, e, f
d, f, b, i
g, d, a, b
c, d, g, b
h, d, e, k
e, f, d, c
k, d, e, h
i, d, e, d

如果你解释你在哪里使用它,以及你已经编码的内容的简短演示,这将有所帮助。

【讨论】:

    猜你喜欢
    • 2021-05-31
    • 2023-03-08
    • 2021-01-05
    • 2022-11-26
    • 1970-01-01
    • 2010-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多