如何拥有独特的随机数?

时间:2010-08-03 11:12:34

标签: java random

这就是我如何在1到6之间生成一个唯一的no并从drawable文件夹中获取适当的图像。

Random rand = new Random();
// n = the number of images, that start at idx 1
rndInt = rand.nextInt(6) + 1; 
String imgName = "card" + rndInt;
int id = getResources().getIdentifier(imgName, "drawable", getPackageName());
imgView.setImageResource(id);

我想要的是,我必须调用此方法7次,并且每次此方法都应该返回一个唯一的随机数。所以没有一个已经选定的数字会再出现。

7 个答案:

答案 0 :(得分:37)

解决此类问题的常用方法是创建一个包含每个可能值的列表并对其进行随机播放(使用Collections.shuffle)。然后,每次需要值时,从列表中使用一个项目。这将确保您不会多次使用相同的值,但仍允许随机顺序。

答案 1 :(得分:8)

这是一个使用Dan Dyer建议的方法创建随机排列的示例类。它确保每个.next()调用给出一个新的数字,直到构造函数中给出的数字。之后,它会缠绕并再次给出相同的序列。 这对于改组播放列表非常有用。

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class RandomPermutation{
    private List<Integer> list;
    private int index;

    /**
     * Create a random permutation the sequence of numbers 0, 1, ... , n - 1.
     * @param n Range specifier, must be positive
     */
    public RandomPermutation(int n) {
        if (n <= 1) {
            throw new IllegalArgumentException(
                    "Positive number expected, got: " + n);
        }
        list = new ArrayList<Integer>();
        newList(n);
    }

    /**
     * Creates a new list
     */
    public void newList(int n) {
        index = -1;
        list.clear();
        for (int i = 0; i < n; i++) {
            list.add(i);
        }
        Collections.shuffle(list);
    }

    /**
     * Retrieve the next integer in sequence. 
     */
    public int next() {
        index = (index + 1) % list.size();
        return list.get(index);
    }
}

顺便说一下。不要使用Snake使用的方法。 这不仅仅是因为一旦使用了所有数字它就会冻结。这可以修复。 问题更多的是,随着越来越多的数字出现在 listIdontWantAnymore 中,程序越来越慢。只有6个数字不是问题,但如果范围很大,它可能会导致相当大的减速。考虑在10000个数字之间选择。选择了9900个数字后,有1%的机会击中一个好数字。在9990之后,有0.1%的机会击中一个好的数字等等。

以下是如何使用该类的示例:

static RandomPermutation randomPerm = new RandomPermutation(7)

int NextRandomNumber() {
    return randomPerm.next() + 1;
}

答案 2 :(得分:2)

这是最简单的代码,可以在不重复的情况下存储到数组中:

Random rand = new Random();
int[] ar;
ar = new int[5];

int random = 0;
int [] result_arr=new int[5];
boolean flag=false;

for(int i=0;i<5;i++)
{  
    ar[i]=0;

    do{
        random =rand.nextInt(10);
        flag=false;
        for(int j=0;j<i;j++)
        {
            if(ar[j]==random)
            flag=true;
        }
        if(!flag)
        {
            ar[i]=random;
            break;
        }
     }
     while(true) ;
}

这将在数组中创建唯一的数字

答案 3 :(得分:1)

对于您的特定用例,这应该可以解决问题。

Random rand = new Random();
// n = the number of images
List<String> imgNames = new ArrayList<String>(n);
for (int i = 0; i < n; i++) { 
    imgNames.add("card" + (i + 1)) 
}
while (!imageNames.isEmpty()) {
    String imgName = imgNames.remove(rand.next(imageNames.size());
    int id = getResources().getIdentifier(imgName, "drawable", getPackageName());
    imgView.setImageResource(id);
}

请注意,当n变大时,这不能很好地扩展。对于O(n)ArrayList,移除操作为LinkedList。但是对于数百或数千的n,与加载和显示图像相比,这可能是微不足道的。

此外,正如评论所指出的“独特随机数”在术语上是矛盾的。你所追求的是从1n的一组数字的随机排列。我的解决方案在没有明确的“改组”步骤的情况下为您提供了这一点,这足以满足您的用例。

答案 4 :(得分:1)

生成包含您将使用的每个号码的数字列表。 (这很好,因为我们正在讨论一个小范围,其中“N”是“不到一千的地方”)

当您选择一个数字时,选择0和sizeof(列表)之间的随机索引,该数字将成为该列表的索引。

删除该列表索引并返回该号码。

(这是一个练习,以确定这里适合的“列表”类型。)

答案 5 :(得分:1)

使用具有适当选择参数的linear congruential generator

答案 6 :(得分:-4)

创建一个您已经获得的可能性的静态列表。

static ArrayList<int> listIdontWantAnymore = new ArrayList<int>();

int NextRandomNumber() {
    Random random = new Random();
    int myRandomInt;

    do {
        myRandomInt = random.NextInt(6) + 1;
    } while(listIdontWantAnymore.Contains(myRandomInt));

    listIdontWantAnymore.Add(myRandomInt);

    // now your 'myRandomInt' is what you want it to be.
    return myRandomInt;
}