5

我想生成 1 到 4、4 范围内的随机数,包括。
这是我的代码:

int num = r.nextInt(4) + 1;  //r is instance of Random.

但是,我在循环中运行上面的代码并且不想重复随机数。现在发生的事情通常是我得到的:
1,1,1,2,3,1,4,2,2,1,4,2,4,4,2,1,4,3,3,1,4,2,4,1作为我的输出。

在这里,虽然数字在范围(1-4)内是随机的,但在前 3 次迭代中经常像数字“1”一样重复。

我正在寻找的是一种在循环中获取非重复随机数的方法。我知道的一种简单方法是在当前迭代和比较之前保留最后一个随机数,但我确信必须有更好的解决方案。
提前致谢。

4

4 回答 4

7

使用random.nextInt(range-1)排除前一个数字的函数将该数字映射到输出数字:

public class Test {
  private final Random random = new Random();
  private final int range;
  private int previous;

  Test(int range) { this.range = range; }

  int nextRnd() {
    if (previous == 0) return previous = random.nextInt(range) + 1;
    final int rnd = random.nextInt(range-1) + 1;
    return previous = (rnd < previous? rnd : rnd + 1);
  }


  public static void main(String[] args) {
    final Test t = new Test(4);
    for (int i = 0; i < 100; i++) System.out.println(t.nextRnd());
  }
}
于 2012-12-13T14:58:58.223 回答
1

由于您拥有的数字多于您必须选择的数字,因此您必须重复一些数字。您所能做的就是尽量减少立即重复的次数。

一种方法是使用 Collections.shuffle ,它允许您以随机顺序获得数字,而无需重复,并且每次都这样做。您可以防止重复最后一个 N 值。

要停止连续重复数字,您可以减小范围并使用模数。

int n = 0, max = 4;
Random rand = new Random();

for(int i = 0; i < numbers; i++) {
   n = (n + rand.nextInt(max-1)) % max;
   int numToUse = n + 1;
   // use this number.
}

这项工作实际上只有max-1可能的值,因为您排除了最后使用的值。

于 2012-12-13T15:00:45.750 回答
1

没有“更好”的答案。你得到一个随机数。检查这一行:

1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1

可能是完全随机的。所以我建议你描述一个更好的要求。您是否总是想要一个与前一个不同的下一个数字?你想在一个特殊的范围内有最多的重复吗?假设在 6 个连续数字内,每个数字都允许出现两次?

如果您提出这样的要求,我们或许可以为您提供帮助。否则我们只能说:你看到的真的是随机的 :)

于 2012-12-13T15:01:03.760 回答
0

这是一个算法:

用数字 1-4 初始化数组 A[4]
设置一个计数器Acnt,A的有效大小。初始化为4
for i in 1 to length(输出序列)
   选择一个从 0 到 Acnt -1 的随机整数 X
   将 A[X] 保存到您的输出序列
   交换(A[X],A[Acnt - 1])
   帐户--
   如果(Acnt == 0)Acnt = 长度(A)

想象 A 是一袋数字 1-4 的球。循环的每次迭代,您都会移除一个球。您只需将球隐藏在数组的末尾,而不是实际从数组中删除,这很昂贵。当您减少袋子中的球数(Acnt)时,您选择的下一个球来自非隐藏球。

当您没有更多球可供选择时,您可以通过将球包中的球数重置为完整计数来取消隐藏球。

这基本上是标准的洗牌算法。

编辑:重新阅读问题,我现在看到他只允许在 1 个数字而不是整个序列之后重复,在这种情况下,您需要做的就是修改 if (Acnt == 0) 到 if(Acnt == length (A) - 1)。

于 2012-12-13T15:19:55.187 回答