c# For loop which selects random values without repeats

Basically I have a for loop:

//Choose random hotspots
_hotspots = zone.GetHotspots();
randomHotSpots = new int[_hotspots.Count];

for (int i = 0; i < numberOfHotspots; i++) {

    randomHotSpots [i] = Random.Range (0, _hotspots.Count);
    Debug.Log ("Hotspot[" + randomHotSpots [i] + "]");

}

Everything works as I need it, except for that it will take duplicate random values. I need the values to be unique, so that if the random number already exists in the array, it should repeat the Random.Range statement until it chooses a unique value which does not exist in the array.

Any ideas?

There are three basic strategies for non repeating random lists.

  • Test that the randomly generated value is unique before adding it to the collection.
  • Create a collection of unique values, then remove them from the collection as you add them to the list.
  • Create a collection of unique values, shuffle them.

Option 1 is best if you have a wide number of possible values, and you are choosing a small portion (eg pick 20 floats between 0 and 1).
Option 2 is best if you are some where in between (eg Pick 20 ints between 0 and 100)
Option 3 is best if you have a limited number of target values, and you are choosing a large portion (eg pick 100 ints between 0 and 100).

1 Like

Actually, I myself had to do this a while ago, so you’re in luck!

While I couldn’t actually find the raw code, I’ll just rewrite it here. (You may want to test this)

//Choose random hotspots
        _hotspots = zone.getHotSpots();
        randomHotSpots = new int[_hotspots.Count];

        List<int> unUsedHotSpots = new List<int> (); //Will store all the hotspots haven't selected

        for(int i = 0; i < _hotSpots.Count; i++){//Firstly, fill unUsedHotSpots with all the value it'll need
            unUsedHotSpots.Add(i);
        }


        for(int i = 0; i < unUsedHotSpots.Count; i++){//You don't need the 'numberOfHotspots' value

            int random = Random.Range(0, unUsedHotSpots.Count);
            randomHotSpots [i] = unUsedHotSpots[random]; //Add the random value to the array

            unUsedHotSpots.RemoveAt (random); //Remove the random value from the unUsedHotSpots list

            Debug.Log ("HotSpot[" + randomHotSpots[i] + "]");
    }
1 Like

Thanks all for your replies. I checked out both of your solutions, and they got me thinking that I needed to dig deeper into Lists, and all of their methods. I think what I ended up with is something like SirHall posted. I build the list of total hotspots, then loop through the amount of hotspots specified, where each iteration removes a random hotspot from the list of total hotspots, and then adds it to the list of selected hotspots. Each time it repeats, the hotspot which was previously chosen cannot be chosen again because it was removed. This actually helped me understand Lists a lot more. Thank you all!

1 Like