[ACCEPTED]-Non-repetitive random number-random

Accepted answer
Score: 23

What exactly do you mean by "should 32 not be repetitive"? If you mean that 31 you don't want to get any duplicates, then 30 you should basically take a list of the 29 numbers 1-20, shuffle them, and then grab 28 one at a time from the head of the list. For 27 an efficient way to shuffle a list, see 26 this Stack Overflow answer.

If you just mean that your current attempt 25 gives 5, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2 24 etc then chances are you're creating a new 23 instance of Random each time you pick a number: don't 22 do that. Each time you create an instance, it 21 will use the current time as the "seed" for 20 the random number generator (unless you 19 specify one explicitly). That means if you 18 create several instances in quick succession, each 17 will get the same seed and therefore give 16 the same sequence of numbers.

Instead, use 15 a single instance of Random and reuse it. (Note 14 that it's not thread-safe though, which 13 is a pain.) For instance:

private static readonly Random Rng = new Random();

public int NextNumber()
{
    return Rng.Next(20) + 1;
}

That won't be thread-safe, but 12 let us know if that's a problem. An alternative 11 is sometimes to pass the Random into the method 10 (which would normally be more complicated, of 9 course):

public int NextNumber(Random rng)
{
    return rng.Next(20) + 1;
}

then the caller can reuse the instance 8 appropriately.

If you want a thread-safe 7 way of generating random numbers, you might 6 want to look at my StaticRandom class in MiscUtil.

(Note that 5 using rng.Next(1, 21) would also work fine - I happen to 4 prefer the version above as I think it reduces 3 the guesswork about inclusive/exclusive 2 boundaries, but it's a matter of personal 1 taste.)

Score: 21

This method will generate all the numbers, and 2 no numbers will be repeated:

/// <summary>
/// Returns all numbers, between min and max inclusive, once in a random sequence.
/// </summary>
IEnumerable<int> UniqueRandom(int minInclusive, int maxInclusive)
{
    List<int> candidates = new List<int>();
    for (int i = minInclusive; i <= maxInclusive; i++)
    {
        candidates.Add(i);
    }
    Random rnd = new Random();
    while (candidates.Count > 0)
    {
        int index = rnd.Next(candidates.Count);
        yield return candidates[index];
        candidates.RemoveAt(index);
    }
}

You can use 1 it like this:

Console.WriteLine("All numbers between 0 and 20 in random order:");
foreach (int i in UniqueRandom(0, 20)) {
    Console.WriteLine(i);
}
Score: 2

I did one this way awhile back. I don't 3 know how it compares to the other methods 2 presented as far as efficiency, randomness, etc. But 1 it seems to work:

List<int> integers = new List<int>() { 1, 2, 3, 4, 5, 6,7, 8, 9, 10, 11, 12 };

Random rnd = new Random();

var ints = from i in integers
           orderby rnd.Next(integers.Count)
           select i;
Score: 2

An IEnumerable implementation, based on Hallgrim's answer:

public class UniqueRandoms : IEnumerable<int>
{
    Random _rand = new Random();
    List<int> _candidates;

    public UniqueRandoms(int maxInclusive)
        : this(1, maxInclusive)
    { }

    public UniqueRandoms(int minInclusive, int maxInclusive)
    {
        _candidates = 
            Enumerable.Range(minInclusive, maxInclusive - minInclusive + 1).ToList();
    }

    public IEnumerator<int> GetEnumerator()
    {
        while (_candidates.Count > 0)
        {
            int index = _rand.Next(_candidates.Count);
            yield return _candidates[index];
            _candidates.RemoveAt(index);
        }
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

0

Score: 0

From MSDN

"One way to improve randomness 4 is to make the seed value time-dependent."

Another 3 fact

you should "create one Random to generate 2 many random numbers over time." This will 1 enhance the random generation

Score: 0
class Program
{
    static void Main(string[] args)
    {        
        List<int> list = new List<int>();
        int val;
        Random r;
        int IntialCount = 1;
        int count = 7 ;
        int maxRandomValue = 8;

        while (IntialCount <= count)
        {
            r = new Random();
            val = r.Next(maxRandomValue);
            if (!list.Contains(val))
            {
                list.Add(val);
                IntialCount++;
            }

        } 
    }
}

0

Score: 0

The following way is very good way, I use 3 a string over here, you can change the type 2 of the list to whatever you want..., try 1 it:

            List<string> NamesList = new List<string>() { "Name1", "Name2", "Name3", "Name4", "Name5" };
            Random rnd = new Random();
            //Now to get random of the above "Without Repeating.."
            for (int i = 0; i <= NamesList.Count - 1; i++)
            {
                int TheSelectedRand = rnd.Next(NamesList.Count);
                string MyRandNumber = NamesList[TheSelectedRand];

                //Print or use your item here

                NamesList.Remove(NamesList[TheSelectedRand]);
            }
Score: 0
static void Main(string[] args)
{
    //Randomize 15 numbers out of 25 - from 1 to 25 - in ascending order
    var randomNumbers = new List<int>();
    var randomGenerator = new Random();
    int initialCount = 1;

    for (int i = 1; i <= 15; i++)
    {
        while (initialCount <= 15)
        {
            int num = randomGenerator.Next(1, 26);
            if (!randomNumbers.Contains(num))
            {
                randomNumbers.Add(num);
                initialCount++;
            }
        }
    }
    randomNumbers.Sort();
    randomNumbers.ForEach(x => Console.WriteLine(x));
}

0

Score: 0

Just like i did:

    list.Clear();
    int count = 0;
    
    while (count < 20)
    {            
        int x = Random.Range(1, 21);
        if (!list.Contains(x))
        {
            list.Add(x);
            count++;
        }
    }

0

More Related questions