- Home /
randomizing arrays
hi folks!
is there a better way to randomize an array like the following one?
theArray = randomizeArray(theArray);
function randomizeArray(arr : Array) : Array { var counter : int = arr.length; var reArr = new Array();
while (counter-- >= 1)
{
var rndM : int = Random.Range(0, arr.length-1);
reArr.push(arr[rndM]);
arr.RemoveAt(rndM);
}
return reArr;
}
thnx!
Why do you need to make a new array? Can't you just read the elements in a random order?
$$anonymous$$y JS is a bit hazy, but it looks like it empties the original array, which is fine if you are setting the return value to the passed array, but if you did array2=randomizeArray(array1), then array1 would be empty, which is a bit of a harsh side-effect.
Answer by duck · May 03, 2010 at 01:23 PM
Here's a slightly simpler version which doesn't create a new array, or add/remove elements to the array. It simply swaps elements around in the original array, giving a very fast algorithm which is useful if this happens to be part of some speed-critical code. (this is called the Fisher Yates shuffle).
static function RandomizeArray(arr : Array)
{
for (var i = arr.length - 1; i > 0; i--) {
var r = Random.Range(0,i);
var tmp = arr[i];
arr[i] = arr[r];
arr[r] = tmp;
}
}
Because this works on the original array, it does not return a result. To use, you would simply call:
RandomizeArray(myArray);
In addition, because this function doesn't rely on adding or removing items, it can also be adapted to work with built-in arrays rather than Unity's Javascript Arrays by simply changing the input parameter type to Object[] rather than Array, and by writing ".length" as ".Length" (change the lower case l to a capital L). Eg:
static function RandomizeBuiltinArray(arr : Object[])
{
for (var i = arr.Length - 1; i > 0; i--) {
var r = Random.Range(0,i);
var tmp = arr[i];
arr[i] = arr[r];
arr[r] = tmp;
}
}
Can someone please convert it in c sharp. i am new to unity.
Sorry for late answer. Here is a C# sample of the code above, as ai_vierus asked. It's a generic method that will shuffle passed built-in array of any type in a very efficient way (Fisher-Yates shuffle).
public static void ShuffleArray<T>(T[] arr) {
for (int i = arr.Length - 1; i > 0; i--) {
int r = Random.Range(0, i);
T tmp = arr[i];
arr[i] = arr[r];
arr[r] = tmp;
}
}
It doesn't have return value, ins$$anonymous$$d it changes the parameter passed. Use this method as below:
ShuffleArray<int>(arr); // in case built-in array is of type int
or via a simpler call:
ShuffleArray(arr);
The function you wrote doesn't randomize, so its not a good function.
Think a bit. Your function just moves the elements and fixes in a position. $$anonymous$$y english is not so good, so I'll expose the problems I've seen with an example. Example: Array("A","B","C");
If you use your function, it'll the the next: 1st step: Grab C (position 3) and save it on tmp 2nd step: Grab A or B and move it to position 3 3rd step: Save C on the empty position Actual array: ("C","B","A") or ("A","C","B") 4th step: Grab position 2 and move it to 1 or viceversa (it's the same)
Final Array: ("B","C","A") or ("C","A","B")
Your randomize function just give 2 solutions!!!!!
There are 6 posible solutions randomizing that array. ("A","B","C") ("A","C","B") ("B","A","C") ("B","C","A") ("C","A","B") ("C","B","A")
So I would say, this randomize function doesnt work as espected, never! If you call the function twice, it get back to the original array. ("B","C","A") -> ("","C","B")->("A","C","B")->("C","A","B") (it's one of your array solutions) ("B","C","A") -> ("B","","C")->("B","A","C")->("A","B","C") -> original And the same for("C","A","B") array. You need to create a new array, like this:
static function RandomizeArray(arr : Array){
var thisarray = new Array(arr);
var temp = Array();
for (var i = arr.Count - 1; i >= 0; i--) {
var r = Random.Range(0,i+1);
temp.Add(thisarray[r]);
thisarray.RemoveAt(r);
}
for (i = 0; i < arr.Count; i++) {
arr[i] = temp[i];
}
}
-JoSe$$anonymous$$- is correct that the provided code is not producing all possible permutations, but it's not because the algorithm is fundamentally flawed. Rather, there's a bug in the code. Random.Range(int $$anonymous$$, int max) returns "a random integer number between $$anonymous$$ [inclusive] and max [exclusive]." - source The exclusion of the max number has bitten me a number of times (the float version of the Random.Range function is inclusive for both $$anonymous$$ and max, so it's easy to forget about this subtlety when switching to the integer version).
So the code for the in-place shuffle should look like this in C#:
public static void ShuffleArray<T>(T[] arr) {
for (int i = arr.Length - 1; i > 0; i--) {
int r = Random.Range(0, i + 1);
T tmp = arr[i];
arr[i] = arr[r];
arr[r] = tmp;
}
}
Likewise, the JavaScript version should include the same change:
static function RandomizeBuiltinArray(arr : Object[])
{
for (var i = arr.Length - 1; i > 0; i--) {
var r = Random.Range(0, i + 1);
var tmp = arr[i];
arr[i] = arr[r];
arr[r] = tmp;
}
}
Answer by -JoSeM- · Aug 14, 2014 at 09:34 AM
I hope this will do the job you need
static function RandomizeArray(arr : Array){
var thisarray = new Array(arr);
var temp = Array();
for (var i = arr.Count - 1; i >= 0; i--) {
var r = Random.Range(0,i+1);
temp.Add(thisarray[r]);
thisarray.RemoveAt(r);
}
for (i = 0; i < arr.Count; i++) {
arr[i] = temp[i];
}
}