2014-01-29 55 views
0

我有一个方法无法正常工作。 该方法应该将一组数字从1到20随机排序(每个数字 必须只出现一次)。 我的问题在于,当我运行程序时,一些数字会重复多次。 代码如下:随机方法问题

public static int randomize(int index) { 

    //This array will hold the 20 numbers. 
    int[] randomIndex = new int[20]; 

    Random ranNum = new Random(); 

    for (int x = 0; x<20; x++) { 
     int temp; 

     //The number is generated randomly and saved in temp. 
     temp = ranNum.nextInt(20); 

     //This loop skips the first index. 
     if (x != 0){ 

      /*Here, the loop is supposed to compare a generated number with 
      the previous one*/ 
      for (int y = 1; y<=x; y++) { 


       while(temp == randomIndex[x-y]) { 

        /*If the while loop finds that temp variable matches any previous       
        number it will generate another random number for it until it finds 
        no matches.*/ 
        temp = ranNum.nextInt(20); 

       } 
      } 
     } 

    /*Once no match has been found for temp, the number is assigned to an index, 
    and the loop is executed with a x variable increment. 
    randomIndex[x] = temp; 

    } 
    //Finally the array with the set of random numbers is sent to the main function. 
    return randomIndex[index]; 

    } 

而且我得到了以下的输出:

19, 19, 5, 16, 6, 2, 18, 1, 15, 1, 5, 19, 11, 4, 18, 0, 5, 18, 10. 

所以,现在我不知道该怎么做。 :C

+1

请问您可以添加关于您的代码*应该*做什么的评论?我认为这也会帮助你调试! –

+0

为什么不使用'List'和'Collections.shuffle()'方法? –

+0

或者至少将已经画出的每个数字添加到列表中,并检查它是否与List.contains(newNumber)重复? – sheltem

回答

1

当您使用Random.nextInt()时,不能保证生成的数字是唯一的。 您应该首先从1到20生成数字,然后洗牌。现在问题变成了“如何随机洗牌”?

也许你可以参考JDK Collections.shuffle()的实现。

该算法为混洗的数字很简单:

  1. 接第一元件阵列中并与多个随机位置交换它。
  2. 重复步骤1直到最后一个元素。
0

您可以通过使用像这样避免:

final Random random = new Random(); 


    final HashSet<Integer> integers = new HashSet<>(); 

    while(integers.size() < 20) { 
     integers.add(random.nextInt(20)); 
    } 

    System.out.println(integers); 
0

它看起来像你试图通过拒绝来生成随机数 - 即由每个随机数与所有以前比较接受的数字,并重新生成新的,直到你找到一个与众不同的数字。

正如其他人所提到的那样,从1到20的数字生成并用随机排列对其进行随机混合会更有效率。但是,如果正确实施,您的方法应该最终......工作。

随机洗牌的实现可能是这个样子:

for(int i=0; i<20; i++) { // index goes from 0..19 
    randomIndex[i] = i + 1; // value goes from 1..20 
} 

for(int i=0; i<20; i++) { 
    int j = i + ranNum.nextInt(20 - i); // choose random j from i <= j < 20 
    int temp = randomIndex[i];   // swap elements i and j 
    randomIndex[i] = randimIndex[j]; 
    randomIndex[j] = temp; 
} 

的两个原因,您发布的代码生成重复。首先,当您拒绝一个候选随机数并重新生成一个新数时,您需要将其与全部现有数字进行比较,从头开始重新启动内部(y)循环。您现有的代码不会这样做。

其次,我相信new Random()构造函数每次调用时都会生成一个不同的种子。如果是这样,那么randomize()函数每次都会生成一个完全不同的随机列表,并从中返回所选的索引。无论如何,返回整个数组更有意义。

0

我编辑的功能,从1到20产生数组:

public static int[] randomize() { 

    int[] randomIndex = new int[20]; 

    Random ranNum = new Random(); 
    boolean isAlreadyIn; 
    boolean isZero; 
    int x = 0; 

    while (x < 20) { 
     isAlreadyIn = false; 
     isZero = false; 
     int temp; 
     temp = ranNum.nextInt(21); 
     for(int i = 0; i < randomIndex.length; i++){ 
      if(temp == 0) 
       isZero = true; 
      if(temp == randomIndex[i]) 
       isAlreadyIn = true; 
     } 
     if (!isZero && !isAlreadyIn){ 
      randomIndex[x] = temp; 
      x++; 
     } 
    } 

    return randomIndex; 
} 

希望这会有所帮助。