Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Strugglin' with Knuth shuffle algorithm

Discussion in 'Scripting' started by ThisIsSparta, Feb 2, 2015.

  1. ThisIsSparta

    ThisIsSparta

    Joined:
    May 4, 2014
    Posts:
    142
    hey all! I'm strugglin a little bit :/

    Code (CSharp):
    1. void reshuffle(string[] texts)
    2.     {
    3.         // Knuth shuffle algorithm :: courtesy of Wikipedia :)
    4.         for (int t = 0; t < texts.Length; t++ )
    5.         {
    6.             string tmp = texts[t];
    7.             int r = Random.Range(t, texts.Length);
    8.             texts[t] = texts[r];
    9.             texts[r] = tmp;
    10.         }
    11.     }
    can someone give an example of this with a public game objects array? ty very much ;)
     
  2. toreau

    toreau

    Joined:
    Feb 8, 2014
    Posts:
    204
    Do you really need to use the Fisher-Yates algorithm for shuffling your gameobjects? I would have opted for a much simpler solution, i.e. something like this (from the top of my head):

    Code (CSharp):
    1. using System.Linq;
    2.  
    3. // ...
    4.  
    5. GameObject[] ShuffleGameObjects ( GameObject[] gameObjects ) {
    6.     System.Random rnd = new System.Random();
    7.  
    8.     return gameObjects.OrderBy( x => rnd.Next() ).ToArray();
    9. }
     
  3. Yemachu

    Yemachu

    Joined:
    Feb 1, 2015
    Posts:
    13
    Replace any instance of the word "string", with the word "GameObject". This function basically switches the indexes of all elements multiple times.

    For each element in the array, this script temporary stores the current value. Then it 'randomly' selects a new position in the array for that element. The content of the random position in the array is then moved to the current position. Now we have a duplicate of one value and lost another value; that is where the temporary value comes to aid. We then store the value of the temporary value in the random position.

    Here is what the result looks like.
    Code (CSharp):
    1. void reshuffle(GameObject[] gameObjects)
    2.     {
    3.         for (int i = 0; i < gameObjects.Length; i++ )
    4.         {
    5.             GameObject tmp = texts[i];
    6.             int r = Random.Range(i, texts.Length);//By replacing 'i' with 0, you might get a more randomized array.
    7.             gameObjects[i] = gameObjects[r];
    8.             gameObjects[r] = tmp;
    9.         }
    10.     }
     
    ThisIsSparta likes this.
  4. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,184
    Actually, if you use 0 instead of i, the shuffle is less random. See here: if you select r (j in the wikipedia article) from the entire possible range, some shuffles become more likely than others.
     
  5. Yemachu

    Yemachu

    Joined:
    Feb 1, 2015
    Posts:
    13
    Allright, didn't know that... it seems like I need to do some more research before stating certain things. Yet, it works either way; only probabilites change.
     
  6. ThisIsSparta

    ThisIsSparta

    Joined:
    May 4, 2014
    Posts:
    142
    first of all thx for your answers :)

    I'm trying with this

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class Random : MonoBehaviour
    5. {
    6.     public GameObject[] draggers;
    7.  
    8.     void Start(GameObject[] gameObjects)
    9.     {
    10.         for (int i = 0; i < gameObjects.Length; i++ )
    11.        
    12.         {
    13.         GameObject tmp = draggers[i];
    14.         int r = Random.Range(0, draggers.Length);//By replacing 'i' with 0, you might get a more randomized array.
    15.         gameObjects[i] = gameObjects[r];
    16.         gameObjects[r] = tmp;
    17.         }
    18.    
    19.     }
    20.  
    21. }
    but it gives me an error : "Random does not contain a definition for Range". can't understand why
     
  7. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,184
    Because you have named your class "Random", meaning that when you write Random.Range, it looks for the method Range in this class.

    There's two ways to fix this:
    1: Give your class a different name.
    2: Write UnityEngine.Random instead of just Random.

    You should pick 1, as the name "Random" isn't a really good name for a class that shuffles a list of GameObjects.
     
    ThisIsSparta likes this.
  8. ThisIsSparta

    ThisIsSparta

    Joined:
    May 4, 2014
    Posts:
    142
    Very good hint! thx and sorry for your time loss! now the shuffling is working...what doesn't work is this

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class Shuffler : MonoBehaviour
    5. {
    6.     public GameObject [] draggers;
    7.     public Vector3 [] positions;
    8.    
    9.     void Start()
    10.     {
    11.         draggers = GameObject.FindGameObjectsWithTag ("Draggers");
    12.         for (int i = 0; i < draggers.Length; i++ )
    13.            
    14.         {
    15.             GameObject tmp = draggers[i];
    16.             int r = Random.Range(0, draggers.Length);
    17.             draggers[i] = draggers[r];
    18.             draggers[r] = tmp;
    19.             draggers[r].transform.position = positions;
    20.         }
    21.        
    22.     }
    23.    
    24. }
    25.  
    seems like I can't give the new r array the positions of the vector 3 array. :/
     
  9. toreau

    toreau

    Joined:
    Feb 8, 2014
    Posts:
    204
    transform.position is a Vector3, not an array of Vector3.
     
  10. ThisIsSparta

    ThisIsSparta

    Joined:
    May 4, 2014
    Posts:
    142
    I think I'm lost...the public vector 3 u see in the script is actually edited in the editor where I gave 3 positions (x,y,z) now I want tmp move to this 3 positions

    so I'm doing

    Code (CSharp):
    1. tmp.transform.position = positions;
    but I know something wrong :(
     
  11. toreau

    toreau

    Joined:
    Feb 8, 2014
    Posts:
    204
    Vector3 is one position consisting of an x, y and z value. If you change "positions" to be a Vector3, and not a Vector3 array, it should work.
     
  12. ThisIsSparta

    ThisIsSparta

    Joined:
    May 4, 2014
    Posts:
    142
    yeah I get it, but the problem is I need this 3 objects coming out from the array tmp moving to 3 differents vector 3.
     
  13. seldom

    seldom

    Joined:
    Dec 4, 2013
    Posts:
    118
    Use
    Code (CSharp):
    1. draggers[r].transform.position = positions[i];
    For code clearity, you may want to assign the positions in a seperate loop after shuffling the GameObjects. Also, i should be the first parameter to Random.Range.
     
    Last edited: Feb 2, 2015