Search Unity

Fill array with random integers

Discussion in 'Scripting' started by herbie, Jun 14, 2013.

  1. herbie

    herbie

    Joined:
    Feb 11, 2012
    Posts:
    237
    You can fill an array with 4 random numbers like this:

    Code (csharp):
    1. arr[0] = Random.Range (0,10);
    2. arr[1] = Random.Range (0,10);
    3. arr[2] = Random.Range (0,10);
    4. arr[3] = Random.Range (0,10);
    If you want to have different random numbers in the array, you can do this:

    Code (csharp):
    1. arr[0] = Random.Range (0,10);
    2. do {
    3.          arr[1] = Random.Range (0,10);
    4.    } while (arr[1] == arr[0]);
    5.    
    6. do {
    7.           arr[2] = Random.Range (0,10);
    8.    } while ((arr[2] == arr[1]) || (arr[2] == arr[0]));
    9.    
    10. do {
    11.           arr[3] = Random.Range (0,10);
    12.    } while ((arr[3] == arr[2]) || (arr[3] == arr[1]) || (arr[3] == arr[0]));
    But this is not the way when you have an array with 100 random numbers.
    For a long time I'm thinking about how to do this in a better way.
    Does anybody know a better way to fill an array with different random numbers?
     
  2. shaderop

    shaderop

    Joined:
    Nov 24, 2010
    Posts:
    942
    If what you want is to fill a collection with a hundred unique random numbers, then you can use a HashSet of integers like so:

    Code (csharp):
    1. var rands = HashSet<int>();
    2. while (rands.Count < 100)
    3.   rands.Add(Random.Range(0, 1000);
     
  3. Amon

    Amon

    Joined:
    Oct 18, 2009
    Posts:
    1,384
    Code (csharp):
    1.  
    2. for ( var iter : int = 0; iter < 100; iter++ ) {
    3.       arr[iter] = Random.Range(0, 101);
    4. }
    5.  
     
  4. herbie

    herbie

    Joined:
    Feb 11, 2012
    Posts:
    237
    Yes, I need a collection with unique random numbers.
    HashSet is new for me.
    It's not clear for me right now how it works. I see you create a list with unique random numbers but how can you select one specific random number from the list?


    Amon:
    In your code you don't get unique numbers and that's what I need. But thanks for reply.
     
  5. EliteMossy

    EliteMossy

    Joined:
    Dec 2, 2012
    Posts:
    513
    The best way is to insert the numbers into an array in order then shuffle the array. You do not need to use Random.Range until shuffeling. This will provide unique numbers in each array element, but shuffled so it's random.

    Code (csharp):
    1.  
    2.     private int[] intArray = new int[100];
    3.  
    4.     private void RandomUnique()
    5.     {
    6.         for (int i = 0; i < 100; i++)
    7.         {
    8.             intArray[i] = i;
    9.         }
    10.         Shuffle(intArray);
    11.     }
    12.  
    13.     public void Shuffle(int[] obj)
    14.     {
    15.         for (int i = 0; i < obj.Length; i++)
    16.         {
    17.             int temp = obj[i];
    18.             int objIndex = Random.Range(0, obj.Length);
    19.             obj[i] = obj[objIndex];
    20.             obj[objIndex] = temp;
    21.         }
    22.     }
    You did not really state what sort of number range you were looking at so i assumed 0-99.
     
    flashframe likes this.
  6. Hikiko66

    Hikiko66

    Joined:
    May 5, 2013
    Posts:
    1,304
    A simple solution.
     
    Last edited: Jun 14, 2013
  7. herbie

    herbie

    Joined:
    Feb 11, 2012
    Posts:
    237
    I think shuffle the array would be the best way for me. Never thought of that.
    Thanks.
     
  8. Jessy

    Jessy

    Joined:
    Jun 7, 2007
    Posts:
    7,325
  9. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    HashSet<T> doesn't provide an indexer but you can copy it to an array after you fill it up.

    Code (csharp):
    1.  
    2. HashSet<int> h = new HashSet<int>();
    3. int[] a;
    4. while (h.Count < 100)
    5. {
    6.     h.Add(Random.Range(0, 100));
    7. }
    8. h.CopyTo(a);
    9. for (var i = 0; i < a.Length; i++)
    10. {
    11.     Debug.Log(a[i]);
    12. }
    13.  
    But, EliteMossy's solution is still the better one.
     
    Last edited: Jun 14, 2013
  10. KevinCodes4Food

    KevinCodes4Food

    Joined:
    Dec 6, 2013
    Posts:
    61
    EliteMossy's technique is known as the Knuth-Fisher-Yates Shuffle. Very useful for randomizing arrays of any type.

    Building on EliteMossy's implementation, I wrote a quick generalized C# template that I use in our code. You can still pass in integer arrays, but any other type of array as well. Perhaps, for example, an array of Gamebject prefabs to shuffle the order in which they spawn.

    Code (csharp):
    1.  
    2. public static void RandomizeArray<T>(T[] array)
    3. {
    4.     int size = array.Length;
    5.     for (int i=0; i < size; i++)
    6.     {
    7.         int indexToSwap = Random.Range(i, size);
    8.         T swapValue = array[i];
    9.         array[i] = array[indexToSwap];
    10.         array[indexToSwap] = swapValue;
    11.     }
    12. }
    13.  
    To call it with integers...

    Code (csharp):
    1.  
    2. //
    3. // Non repeating random numbers from 0 to count
    4. //
    5.  
    6. int[] indexArray = new int[count];
    7.        
    8. // Fill with sequeential indexes then randomize
    9. for(int i=0; i<indexArray.Length; ++i)
    10.     indexArray[i] = i;
    11.  
    12. RandomizeArray<int>(indexArray);
    13.  
    14.  
    To call it with game object prefabs

    Code (csharp):
    1.  
    2. //
    3. // Non repeating prefab spawn
    4. //
    5. public GameObject arrayOfPrefabsToSpawn[]; // An array of the prefabs that should be spawned
    6.        
    7. RandomizeArray<GameObject >(arrayOfPrefabsToSpawn);
    8.  
    9. // Now just sequentially instantiate the prefab gameobjects in the arrayOfPrefabsToSpawn as needed.  
    10. // You can, of course, just call RandomizeArray again when the end is reached and start the spawn loop again.
    11. for(int i=0; i<arrayOfPrefabsToSpawn.Length; ++i)
    12. {
    13.     GameObject.Instatiate(arrayOfPrefabsToSpawn[i]);
    14.     yield return new WaitForSeconds(spawnDelay);
    15. }
    16.  
    17.  
    18.  
     
  11. Rphysx

    Rphysx

    Joined:
    Mar 26, 2014
    Posts:
    54
    I've come up to this after few tries and it seems to work nice and well and it gives truly random unique numbers. Just test it and tell me if it works for you

    Code (csharp):
    1.  
    2. public static class ShuffleLike
    3.     {
    4.         public static int[] arr = new int[100];
    5.         public static Random R = new Random();
    6.         public static int Aint;
    7.         public static List<int> IntList= new List<int>();
    8.  
    9.  
    10.  
    11.         public static void FillList()       //Static method to call            
    12.         {
    13.             for (int i = 1; i < 101; i++)
    14.             {
    15.                 IntList.Add(i);
    16.             }
    17.             FillArray();
    18.         }
    19.  
    20.         static void FillArray()
    21.         {
    22.             for (int i = 0; i < 100; i++)
    23.             {
    24.                 Aint = R.Next(0, IntList.Count);
    25.                 arr[i] = IntList[Aint];
    26.                 IntList.RemoveAt(Aint);
    27.             }
    28.         }
    29.     }
    30.