Quick Tip: How to Randomly Shuffle an Array in AS3
Tutorial Details
- Difficulty: Beginner
- Platform: Flash (Flash Player 9+)
- Language: AS3
- Software used: Any AS3 compiler
- Estimated Completion Time: 10 minutes
- Icon: Based on work by YaroManzarek on deviantART
Sometimes you have a set of items — could be Strings, could be Numbers, could be Objects, whatever — whose order you want to randomise. This is particularly useful for quizzes and games of chance, but comes in handy in all sorts of other applications. The easiest method I’ve found for doing this is to stick all the items in an Array and then shuffle it like a deck of cards. But how can we do that…?
As a simple example, we’ll use the letters of the alphabet:
var letters:Array = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"];
There are different approaches we can take to actually sorting this array.
The Naive Approach
We could create a second array, and copy each element of the first into a random position in the second:



The code for that might look like this (see this Quick Tip on getting a random integer within a specific range for more details):
var letters:Array = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"];
var shuffledLetters:Array = new Array(letters.length);
var randomPos:int = 0;
for (var i:int = 0; i < letters.length; i++)
{
randomPos = int(Math.random() * letters.length);
shuffledLetters[randomPos] = letters[i];
}
But there’s one huge problem. What if the random position picked for C is 6 as well?

Here, A gets overwritten, and will therefore not be in the shuffled array. That’s not what we want, so we need to check that the slot is empty before copying the letter over, and pick a different slot if it isn’t:
var letters:Array = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"];
var shuffledLetters:Array = new Array(letters.length);
var randomPos:int = 0;
for (var i:int = 0; i < letters.length; i++)
{
randomPos = int(Math.random() * letters.length);
while (shuffledLetters[randomPos] != null) //repeat as long as the slot is not empty
{
randomPos = int(Math.random() * letters.length); //pick a different slot
}
shuffledLetters[randomPos] = letters[i];
}
That works. Problem is, it’s inefficient. See, the letter A is guaranteed to fit into the slot picked, because it’s the first letter chosen, so all the slots will be empty. With B, there’s a 25 in 26 chance that the first slot picked will be empty. When we’re half-way through the alphabet, this chance drops to 50/50. By the time we reach V, there’s a 50/50 chance that we won’t find an empty slot until the fourth attempt.
This means we’re very likely to be calling Math.random() wayyyyy more than 26 times. And Math.random() is a relatively slow function. What’s another approach we can take?
The Middle-Man Approach
What if we stored a list of all the empty slots in a third array, which would shrink as we went through them?





…and so on, repeating until the array of empty slots contains no elements. The code for that would look like this:
var letters:Array = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"];
var shuffledLetters:Array = new Array(letters.length);
var emptySlots:Array = new Array();
for (var n:int = 0; n < letters.length; n++)
{
emptySlots.push(n);
}
var randomPos:Number = 0;
var actualSlot:Number = 0;
for (var i:int = 0; i < letters.length; i++)
{
randomPos = int(Math.random() * emptySlots.length); //note emptySlots.length not letters.length
actualSlot = emptySlots[randomPos];
shuffledLetters[actualSlot] = letters[i];
emptySlots.splice(randomPos, 1);
}
Here we use the Array.splice() method to remove a single element from the list of empty slots. This actually removes the element, rather than just setting its value to null; so, after splicing the first slot, emptySlots.length will be 25 rather than 26.
This splice() function is great; we can use it for a third approach to shuffling that cuts out this middle man array.
The Splicing Approach
Instead of removing elements from the array of empty slots when we’re done with them, we could remove them from the original, unshuffled array.
This doesn’t sound very useful at first — but what if we picked elements from the original array at random, instead of picking their destinations at random?





…and so on, until the first array contains no elements.
Unlike the other two approaches, we end up without the original array. Whether this is a problem or not depends on this project.
The code could look like this:
var letters:Array = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"];
var shuffledLetters:Array = new Array(letters.length);
var randomPos:Number = 0;
for (var i:int = 0; i < shuffledLetters.length; i++) //use shuffledLetters.length because splice() will change letters.length
{
randomPos = int(Math.random() * letters.length);
shuffledLetters[i] = letters[randomPos]; //note this the other way around to the naive approach
letters.splice(randomPos, 1);
}
In fact, since splice() returns an Array of all the elements you are splicing, we could simplify the code a little:<
var letters:Array = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"];
var shuffledLetters:Array = new Array(letters.length);
var randomPos:Number = 0;
for (var i:int = 0; i < shuffledLetters.length; i++)
{
randomPos = int(Math.random() * letters.length);
shuffledLetters[i] = letters.splice(randomPos, 1)[0]; //since splice() returns an Array, we have to specify that we want the first (only) element
}
That’s neater. I’ve got one more approach to share; this one is very different to the others we’ve used so far.
The Sorting Approach
Arrays have a method, sort(), which by default rearranges all the elements of the array into ascending alphanumerical order, like so:
var mixedLetters:Array = ["G", "B", "P", "M", "F"]; mixedLetters.sort(); //mixedLetters is now ["B", "F", "G", "M", "P"]
You can pass options to this method, like Array.DESCENDING, which reverses the order of the sort:
var mixedLetters:Array = ["G", "B", "P", "M", "F"]; mixedLetters.sort(Array.DESCENDING); //mixedLetters is now ["P", "M", "G", "F", "B"]
(There are other options, and you can pass as many of them as you like.)
You can also pass a reference to a function, which tells Flash how to decide which order any two items belong in. For example, this function could be used for numeric sorting:
function numericalSort(a:Number, b:Number):Number
{
if (a < b) return -1;
if (a == b) return 0;
if (a > b) return 1;
}
Flash looks at each pair of adjacent items in the array, and rearranges them according to this function: it swaps them if the value 1 is returned, and leaves them alone otherwise. (Unless you pass Array.DESCENDING as well as the function, in which case it swaps them if the value -1 is returned, and leaves them alone otherwise.) Flash repeats this across the whole array over and over again until all pairs return 0 or -1 (0 or 1 if using Array.DESCENDING).
We can mess with this. Instead of giving it a genuine reason why any two elements should be swapped, we can just tell it to swap them at random, using a sort function like this:
function randomSort(a:*, b:*):Number //* means any kind of input
{
if (Math.random() < 0.5) return -1;
else return 1;
}
Easy! Now we can use it in our code like so:
function randomSort(a:*, b:*):Number
{
if (Math.random() < 0.5) return -1;
else return 1;
}
var letters:Array = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"];
letters.sort(randomSort);
//(no need for the shuffledLetters[] Array)
Please note that the resulting array will not be as randomly shuffled as the other approaches we’ve used — in this approach, there isn’t an even 1/26 chance that any given letter will end up in any given slot. This is because we’re only swapping adjacent pairs of elements, and doing no more than that. Still, it’s a neat method :)
There are plenty of other methods, I know. Got any you like better than these?
Edit: Here’s a great post with some very cool visualisations, explaining the Fisher-Yates shuffle, which works in place. I highly recommend it!

Nice article Michael. One thing that I would add is that if someone is using the splice approach and needs to keep the original then they can just copy the original array and shuffle the copy. The slice() or concat() methods will produce shallow copies and if you need a deep copy then the byteArray can be used (an example is provided in the AS3 Developer’s Guide).
Great tips, thanks Adam!
Using the last approach (sort) in a quick test, Math.random() will be called more than 90 times (one test gave me 91, another 96).
A simple approach that I like that doesn’t create new Arrays (aside from specifically creating a new one, splice() returns a new Array) is this:
var letters:Array = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"];
var len:int = letters.length;
for ( var i:int = 0; i < len; i++ )
{
// choose a random location and hold what's there
var ran:int = int( Math.random() * len );
var char:String = letters[ran];
// now swap them
letters[ran] = letters[i];
letters[i] = char;
}
No new arrays, Math.random() called a total of 26 times, and each letter is guaranteed to get sorted once
Another approach would be to simply choose two entries out of the list and swap them. Repeat as often as desired.
Smart bit of code there Damian!
Had to read it a few times to understand the method it was using, but once I figured it out I realised just how elegant that solution is.
Great article!! thanks~ :)
Thank you for sharing~~~~~~~~
thanks a lot for Article :D
I’m an AS3 newbie… I could easily follow this tutorial and it was helpful for what I was trying to do. But there’s one thing I don’t completely grasp.
In the sorting approach the custom sorting function called randomSort() is set up to return either the value 1 or -1.
That’s the only part I didn’t understand. What does the sort method do with return values? What does the value 1 do? What does -1 do?
Thanks
… about my previous comment… nevermind. I figured it out. I somehow missed the explanation. It’s all there. Sorry :)
You have a bug in your middle man approach. You instantiate the ‘emptySlots’ array as follows…
var emptySlots:Array = new Array(letters.length);
…which means emptySlots.length is 26. Then you append 26 integers onto the end of the ‘emptySlots’ array…
for (var n:int = 0; n < letters.length; n++)
{
emptySlots.push(n);
}
…which means emptySlots.length is now 52, causing NaN errors and index out of range errors. To solve the problem, you should be instantiating the ‘emptySlots’ array like this:
var emptySlots:Array = [];
Excellent point, thanks Rob! I’ve corrected the post.
Nice man you really saved me. Maintain!!!