Say you want to generate 1,000 unique random numbers and present them to some code one at a time. When you exhaust those numbers, you want to present the same numbers again, but in a different sequence.
To generate the numbers, use a hash table. In C#, it would look like this:
const int MaxNumbers = 1000;
HashSet<int> uniqueNumbers = new HashSet<int>();
Random rnd = new Random();
// generate random numbers until there are 1000 in the hash table
while (uniqueNumbers.Count < MaxNumbers)
{
uniqueNumbers.Add(rnd.Next());
}
// At this point you have 1,000 unique random numbers
// Put them in an array
int[] myNumbers = uniqueNumbers.ToArray();
This works because the HashSet.Add
method rejects duplicates. And it's very fast because lookup in the hash table is O(1).
Now, you can serve them by setting a current index at 0 and increment it every time a number is requested. Something like:
int ixCurrent = 0;
int GetNextNumber()
{
if (ixCurrent < MaxNumbers)
{
++ixCurrent;
return myNumbers[ixCurrent-1];
}
But what to do when ixCurrent
runs off the end of the array? Enter the Fisher-Yates Shuffle:
// out of numbers. Shuffle the array and return the first one.
for (int i = MaxNumbers-1; i > 0; --i)
{
int j = rnd.Next(i+1);
int temp = myNumbers[i];
myNumbers[i] = myNumbers[j];
myNumbers[j] = temp;
}
ixCurrent = 1;
return myNumbers[0];
}
If you know that the numbers you want to return are within a particular range (that is, you want to return the numbers 0-999 in random order), then you just fill an array with the values 0-999 and shuffle it.