Random Number without repeat

Hi.

I want create a random number between (1-5) without repeating. so i wrote this code but it give me repeat number. actually i don’t know how can compare a value in array list. how can i fix this problem?

    int Rand;
    int[] LastRand;
    int Max = 6;

    void Start ()
    {
        LastRand = new int[Max];

        for (int i = 1; i < Max; i++)
        {
            Rand = Random.Range(1,6);

            for (int j = 1; j < i; j++)
            {
                while (Rand == LastRand[j])
                {
                    Rand = Random.Range(1, 6);
                }
            }

            LastRand[i] = Rand;
            print(Rand);
        }
    }

Thanks.

Using a list, you could generate a random number, check if the list contains the number, and if not, add it. If so, generate another random number. However, you could probably use the array contains as well. Array.contains Function | Microsoft Learn

There are also several examples on this forum of how to generate a random list of numbers without repeats. Including one that describes several options on how to do this, I just don’t have links to the post atm.

2 Likes

Use this:

public static List<int> GenerateRandom(int count, int min, int max)
        { 
            if (max <= min || count < 0 ||
                    (count > max - min && max - min > 0))
            {
                throw new ArgumentOutOfRangeException("Range " + min + " to " + max +
                        " (" + ((Int64)max - (Int64)min) + " values), or count " + count + " is illegal");
            }

            HashSet<int> candidates = new HashSet<int>();

            for (int top = max - count; top < max; top++)
            {
                if (!candidates.Add(random.Next(min, top + 1)))
                {
                    candidates.Add(top);
                }
            }

            List<int> result = candidates.ToList();
 
            for (int i = result.Count - 1; i > 0; i--)
            {
                int k = random.Next(i + 1);
                int tmp = result[k];
                result[k] = result[i];
                result[i] = tmp;
            }
            return result;
        }

Use it in the start for example:

GenerateRandom(5, 1, 6);
2 Likes

Thanks, I wrote it. it’s very easy.

    int Rand;
    int Lenght = 6;
    List<int> list = new List<int>();

    void Start ()
    {
        list = new List<int>(new int[Lenght]);

        for (int j = 1; j < Lenght; j++)
        {
            Rand = Random.Range(1,6);

            while (list.Contains(Rand))
            {
                Rand = Random.Range(1,6);
            }

            list[j] = Rand;
            print(list[j]);
        }
   
    }
4 Likes

Thanks for code.:slight_smile:

List<int> list = new List<int> (){1,2,3,4,5};
int randNumber = 4;
bool exists = list.Contains(randNumber);

Oops, too late!

1 Like

in your sczenario, a typical approach is to fill the list with all potential outcomes and remove the drawn items from the list.
Pseudo code

pos=Random.Range(0, list.length)
random = list[pos]
List.deleteAtIndex(pos)

3 Likes

@sngdan

  • Create a mutable list with all the options.
  • Use the RNG to pick an index into that list.
  • Delete the corresponding item from the list.
  • Return or use the selected random number.

Alternatively, you can just create a list or queue with all the items in their pre-randomized state, then pull from one end of the collection. That has no real impact, though. It’s just about where you want your design and when you want to execute the random-number-generation calls.

1 Like

I wrote this code and work very well. but when I change start value form 1 to 0 in for loop, it don’t work correctly. because list.Contains(0) is exist. how can fix this problem?

    int Rand;
    int Lenght = 6;
    List<int> list = new List<int>();
    void Start ()
    {
        list = new List<int>(new int[Lenght]);
        for (int j = 1; j < Lenght; j++)
        {
            Rand = Random.Range(1,6);
            if (list.Contains(Rand))
            {
                Rand = Random.Range(1,6);
            }
            list[j] = Rand;
            print(list[j]);
        }
  
    }
    int Lenght = 6;
    List<int> list = new List<int>();
    void GenerateRandom()
    {
        for (int j = 0; j < Lenght; j++)
        {
            int Rand = Random.Range(0,6);
            while(list.Contains(Rand))
            {
                Rand = Random.Range(0,6);
            }
            list.add(Rand);
            print(list[j]);
        }
}

What do you mean by 0 is already added?

Your code has a bug. You must use while instead of if, like Brathnann does above.

this is what i meant in my post above…

    void Start ()
    {
        int startNumber = 1;
        int endNumber = 10;
        List<int> numberPot = new List<int>();
        for (int i = startNumber; i < endNumber + 1; i++)
        {
            numberPot.Add(i);
        }
       
        while (numberPot.Count > 0)
        {
            int index = Random.Range (0, numberPot.Count);
            int randomNumber = numberPot[index];
            numberPot.RemoveAt(index);
            Debug.Log(randomNumber);
        }
    }
1 Like

Thanks, my mistake is relate to this line list = new List(new int[Lenght]);
because it set all index values to 0 and make don’t work correctly.

The problem with the approach to re-roll the random number in case it has come up before is that you can get stuck in the while loop for a long time. If you only have 6 values it does not matter much though.

now, I wrote this code for my game and when Rand value is great than 0 unity give me an error. for example when Rand value is great than 0, my RandBonusList length is less than Rand value. anyone know how can fix it? I don’t want it generate regular number (for example: 0, 1, 2).

            List<int> RandBonusList = new List<int>();
          
            void Start()
            {
                Rand = Random.Range(0, 3);

                while (RandBonusList.Contains(Rand))
                {
                    Rand = Random.Range(0, 3);
                }

                RandBonusList[Rand] = Rand;

                print(RandBonusList[Rand]);
            }

You cannot add to a list’s index that’s not initialized (I think that’s the proper wording).
You’ve gotta fill the list first. Fill it with something you don’t want. Originally , you said you wanted 1-5, so you could fill it with zero or any number not 1-5. if you wanted 0, fill it with 10 or -1 or whatever.
Then, when you have ‘x number’ of spots filled, you can work on it like the code you posted more properly. :slight_smile:

List<int> RandBonusList = new List<int> { 10,10,10,10,10 }; // however many spots you want.
1 Like

Thanks methos5k. :slight_smile:

no problem. Just lending a hand to this … long thread :wink: smiles. Hope it all works out for ya.

@behdadsoft

If you want to stick with your approach, you don’t need to initialize the list, you can add to a list just like this: RandBonusList.Add(Rand). I have the feeling though that you are on the wrong track with you approach.

I recommend you to look at my post #12 and try to understand it (unless I completely did not get what you want).
You basically throw numbers in a pot and then pick them one by one randomly until the pot is empty.

1 Like

There isn’t anything wrong with the approach. It’s actually pretty fast with a small amount of numbers that you’ll never notice it. There are many ways to generate a random list of numbers and what works best usually depends on the size. But on a small set like this, you’ll not notice much difference between what method is chosen.