How to have unique random number?

2019-01-23 22:01发布

问题:

This is how i am generating a unique no in between 1 to 6 and getting appropriate images from the drawable folder.

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);

What i want is, I have to call this method 7 times, and each time this method should return a unique random no. so that none of the already chosen numbers will come up again.

回答1:

The usual approach to this kind of problem is to create a list containing each of the possible values and shuffle it (use Collections.shuffle). You then consume one item from the list each time you need a value. This will ensure that you don't use the same value more than once but still allows for a random order.



回答2:

Here is an example class which creates a random permutation using the approach Dan Dyer suggested. It ensures that each .next() calls gives a new number up to the number given in the constructor. After that it wraps around and gives the same sequence again. This can be useful for shuffling a playlist.

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);
    }
}

Btw. do not use the approach Snake used. It is not only because it will freeze once all numbers have been used. That can be fixed. The problem is more that the procedure runs slower and slower as more and more numbers are in the listIdontWantAnymore. With just 6 numbers it's not a problem, but it can cause quite a significant slowdown if the range is large. Consider choosing between 10000 numbers. After 9900 numbers have been chosen there is a 1% chance of hitting a good number. after 9990 numbers there is a 0.1% chance of hitting a good number and etc.

Here is an example of how you can use the class:

static RandomPermutation randomPerm = new RandomPermutation(7)

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


回答3:

Here's the easiest code to do it and store into an array without any repetition:

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) ;
}

this will create unique numbers in the array



回答4:

For your particular use-case, this should do the trick.

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);
}

Beware that this does not scale well as n gets large. The remove operation is O(n) for an ArrayList or a LinkedList. But for n in the hundreds or thousands, this is probably insignificant compared with loading and displaying the images.

Also, as the comments noted "unique random numbers" is a contradiction in terms. What you are after is a random permutation of the set of numbers from 1 to n. My solution gives you this without an explicit "shuffling" step, and that's sufficient for your use-case.



回答5:

Generate a list of numbers containing every number you will use. (Which is fine, given that we are talking about a small range, where "N" is "somewhere less than a thousand")

When you choose a number, select a random index between 0 and sizeof(list), that number becomes the index of that list.

Delete that list index and return the number.

(It is an exercise to the reader to determine what kind of "list" is appropriate here.)



回答6:

Use a linear congruential generator with appropriately chosen parameters.



回答7:

Create a static list of possibilities you've already gotten.

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;
}


标签: java random