Randomizing numbers on a list.

Im doing a simple Quiz game and I needed a way to get unique random numbers, so I can play the questions in a random order without repeating them. Found the code.

    private int maxNumbers = 6;
    private List<int> uniqueNumbers;
    private List<int> finishedList;

  void Start ()
    {
        uniqueNumbers = new List<int>();
        finishedList = new List<int>();

        GenerateRandomList();
    }

  public void GenerateRandomList()
    {
        for (int i = 0; i < maxNumbers; i++)
        {
            uniqueNumbers.Add(i);
        }
        for (int i = 0; i < maxNumbers; i++)
        {
            int ranNum = uniqueNumbers[Random.Range(0, uniqueNumbers.Count)];
            finishedList.Add(ranNum);
            uniqueNumbers.Remove(ranNum);
        }

        //Just to see them in the console
        foreach (int data in finishedList)
        {
            Debug.Log(data);
        }
    }

The problem here is that the random numbers appear all in once. I need one number at a time and the next randomization just start when I want to, by pressing a button or whatever.
But that’s just the way I feel I can do. For sure there’s a way to do with the numbers all in once in the list.

What you want is the Fisher-Yates Shuffle, my friend!

…and a video!

Edit - I made it so your script works the way you kind of described it wanting.
 private int maxNumbers = 6;
 private List<int> uniqueNumbers;
 private List<int> finishedList;
      
void Start ()
 {
 uniqueNumbers = new List();
 finishedList = new List();
      
              
  }
      
public void GenerateRandomList()
 {
for (int i = 0; i < maxNumbers; i++)
 {
uniqueNumbers.Add(i);
 }
 for (int i = 0; i < maxNumbers; i++)
 {
 int ranNum = uniqueNumbers[Random.Range(0,uniqueNumbers.Count)];
 finishedList.Add(ranNum);
 Debug.Log(ranNum); 
 uniqueNumbers.Remove(ranNum);
                  
  }
      
              
 }
 void OnGUI()
 {
if (GUI.Button(new Rect(100, Screen.height - 175, 100, 30), "Print num"))
{
GenerateRandomList();
}

Perhaps I am not understanding the question, but…

Wouldnt this be as simple as…

int PickAndRemoveOneRandom()
{
int randomNum = Random.Range(0, myList.Count); //Pick one random number based on total numbers.
int theNumber = myList[randomNum]; //store the number
myList.Remove(randomNum); //Remove number so it cant be used again.
return theNumber; //return the number
}

Then use the method in your code

int theNumber = PickAndRemoveOneRandom();

Or onClick event on a Unity UI Button → PickAndRemoveOneRandom() and add your " //do stuff code" in the function instead of returning an int

Options:

  • You could pass the list as parameter: void myMethod(List myList) { }
  • You could make this support generic types (return & remove ANY type from any List, insuring uniqueness
  • Keep used numbers in a second List (just add one line before return. usedNumberList.Add(theNumber)

This is preety old but I was looking for an answer to the same question and I ended writing an algorithm my self. Seems to work preety well.

//"from" and "to" are inclusive
   public List<int> GenerateRandomIntegerList(int from, int to) 
    {
        List<int> numbersDone = new List<int>();

        while (true)
        {
            int i = Random.Range(from, to + 1);

            bool isNew = true;
            foreach (int num in numbersDone)
            {
                if (num == i)
                {
                    isNew = false;
                }
            }

            if(isNew)
            {
                numbersDone.Add(i);

                if(numbersDone.Count == to + 1)                
                    break;
                
            }
        }

        return numbersDone;
    }

Just for the sake of completeness, since all the other answers seem to be pretty good already, but I usually do this using a Set structure (HashSets of int in particular).

If you know your numbers beforehand:
Here’s some pseudo-code:

 - Let there be an empty Set of type Set of Integers called 'SortitionSet'
 - Let there be an Integer Array containing the numbers we want to Sortition called 'IntegersArray'

  Generate the SortitionSet:
    While(Length of  IntegersArray > 0)
         Let there be an auxiliary variable which receives a the resulting element from the deletion of the first element of the array called 'aux'
         Try to insert aux into SortitionSet (It should return false in case of a repeated number)
          In case the insertion was successful continue, otherwise throw exception

    Return SortitionSet

Give a Random Number from the Set by Removing it:
     Return SortitionSet.Remove(Random Index)
    

</end>

If you don’t know your numbers beforehand:

Here’s some pseudo-code:

<begin/>

 - Let there be an empty Set of type Set of Integers called 'SortitionSet'
 - Let there be a positive Integer number greater than zero called 'AmountOfNumbersToGenerate'

  Then:
    While(AmountOfNumbersToGenerate > 0)
         Let there be an auxiliary variable which receives a randomly generated number called 'aux'
         Try to insert aux into SortitionSet (It should return false in case of a repeated number)
          In case the insertion was successful reduce AmountOfNumbersToGenerate by 1

    Return SortitionSet

</end>

Hope this helps someone! Cheers!