10

To generate Random numbers from 1- 20 I need to pick selective and it should not be repetitive.

How to do this in C#

Note I need to loop through as like this

Random rnd = new Random()
rnd.Next(1,20)
for(int i =0; i<=20;i++)
{

}

For all the loops number should be 1 to 20

John Saunders
  • 160,644
  • 26
  • 247
  • 397
web dunia
  • 9,381
  • 18
  • 52
  • 64

10 Answers10

23

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

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

Instead, use a single instance of Random and reuse it. (Note that it's not thread-safe though, which 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 let us know if that's a problem. An alternative is sometimes to pass the Random into the method (which would normally be more complicated, of course):

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

then the caller can reuse the instance appropriately.

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

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

Community
  • 1
  • 1
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • This is because the RNG is seeded based on the time by default, and the loops are well too fast for the level of precision it uses. – Lucas Jones Jun 18 '09 at 07:20
  • What does "not thread-safe" mean? Will i get the same random value in different threads? – Nick Jun 18 '09 at 08:24
  • It means if you try to use the same instance from multiple threads without any kind of locking, Bad Things could happen. In particular, I think it's possible to effectively "break" an instance of Random if you're particularly unlucky, so it ends up with a current state which always repeats. – Jon Skeet Jun 18 '09 at 09:00
21

This method will generate all the numbers, and 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 it like this:

Console.WriteLine("All numbers between 0 and 20 in random order:");
foreach (int i in UniqueRandom(0, 20)) {
    Console.WriteLine(i);
}
Hallgrim
  • 15,143
  • 10
  • 46
  • 54
2

I did one this way awhile back. I don't know how it compares to the other methods presented as far as efficiency, randomness, etc. But 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;
Chris Dunaway
  • 10,974
  • 4
  • 36
  • 48
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();
    }
}
Community
  • 1
  • 1
Ohad Schneider
  • 36,600
  • 15
  • 168
  • 198
0

From MSDN

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

Another fact

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

Ahmed
  • 7,148
  • 12
  • 57
  • 96
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++;
            }

        } 
    }
}
toro2k
  • 19,020
  • 7
  • 64
  • 71
Pradeep Ly
  • 26
  • 1
0

The following way is very good way, I use a string over here, you can change the type of the list to whatever you want..., try 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]);
            }
Adel
  • 1,468
  • 15
  • 18
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));
}
Al Foиce ѫ
  • 4,195
  • 12
  • 39
  • 49
whiteCode
  • 11
  • 1
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++;
        }
    }
-1

blow code generates 65 unique random number between 0 - 92 and return that unique random numbers in an array.

public static int[] RandomNumbers_Supplier()
        {
            Random R = new Random();
            int[] RandomNumbers = new int[65];
            int k = 0, Temp;
            bool IsRepetitive = false;
            while (k < 65)
            {
                Temp = R.Next(0, 92);
                for (int i = 0; i < 65; i++)
                {
                    IsRepetitive = false;
                    if (RandomNumbers[i] == Temp)
                    {
                        IsRepetitive = true;
                        break;
                    }                    
                }
                if (!IsRepetitive)
                {
                    RandomNumbers[k] = Temp;
                    k++;
                }
            }
            return(RandomNumbers)
        }
Meisam
  • 1