The Math object in ActionScript contains a number of methods that perform mathematical operations. Among these is random(), which generates an apparently random number between 0 and 1. To generate a random-number value and assign it to a variable, use a statement like this:
someVariable = Math.random();
Note that the "M" in Math must always be capitalized. The names of predefined objects are always given this way.
Technically speaking the output of Math.random() is only pseudo-random, because the technique used to generate its values will display a detectable pattern if it is repeated enough times. But unless you have the patience to scrutinize hundreds of thousands of repetitions, you probably won't notice.
Below are five movies showing Math.random() in action. In each movie a script displays randomly generated numbers or words.
The script is installed within a Movie Clip called scripts, which appears in the upper right corner of the movie window. This element may look like a button but it's just a convenient place to park the scripts. In a real project we'd probably make this Movie Clip invisible.
Some scripters prefer to place general scripts in the first frame of a layer devoted exclusively to scripting. This is an even simpler solution.
Also on the right side you'll find a button marked Repeat. This button invokes a function defined within the Scripts Movie Clip. This allows you to re-run the demonstration function as many times as you like.
The first demonstration movie below shows the results of Math.random() invoked four times.
By themselves, long decimal numbers between 0 and 1 are not much help in controlling Flash movies. To select from among a range of elements, you'll probably want to match the output of Math.random() against a series of tests, as in this example:
if(randyItem == 0) loadMovie("firstCourse.swf",0);
if(randyItem == 1) loadMovie("secondCourse.swf",0);
if(randyItem == 2) loadMovie("thirdCourse.swf", 0);
if(randyItem == 3) loadMovie("fourthCourse.swf", 0);
if(randyItem == 4) loadMovie("fifthCourse.swf", 0);
These five lines allow you to choose a new movie at random and load it over the present movie.
As you can see, the if tests here assume we're dealing with integers. Two steps are required to get from the raw output of Math.random() to useful integer values.
First, multiply the output of Math.random() by the number of items from which you wish to choose. In the example above we'd multiple by 5:
someVariable = Math.random()*5;
Here's what this change does to our initial example:
As you can see, when you multiply an integer like 5 by a messy decimal number like 0.427009978920274, the result is itself a messy decimal (2.13504989460137, to be exact).
We need a simple integer. To clean up the results we apply another method of the Math object called floor(). This method rounds the decimal down to the nearest integer. In the case above, it yields 2. The statement looks like this:
someVariable = Math.floor(Math.random()*5);
Be careful with those embedded parentheses; you have to get them just right.
Here are four more iterations of Math.random(), this time multiplied by 5 and rounded down with Math.floor():
If you study the output above, you'll see that the random values may include 0 but never include 5. That's because we're always rounding down. If we wanted to include 5 and exclude 0, we'd use the Math.ceil() function instead of Math.floor().
Which function you choose depends on what you want to do with the random value. In many cases you may want to do something slightly different from the example discussed earlier (a series of if tests). You may want to extract a randomly-chosen value from a specially constructed object called an Array. At heart, Arrays are simply ordered lists, though their numbering systems differ from everyday practice in one respect: they always start at 0.
Arrays are numbered from 0 to one less than their total length--from 0 to 14 for a fifteen-element array. Thus the numbers generated by a random function rounded down with Math.floor() will always correspond to indices of the array. If we write an array containing fifteen words, we can now use Math.floor(Math.random()*15)) to generate a random word list:
Constraining Random ValuesIf you re-run the example above a few times, you'll notice that it often contains duplicate items, and that these duplicates may occur one after another. This happens because we're choosing from a relatively small range of options, and because nothing prevents the script from generating the same random integer twice in succession. (Technically speaking, the problem lies with the Math.floor() operation, which takes nearly unique decimals and rounds down to a much smaller range of integers.)
You can minimize repetition by keeping track of the random function's past performance and screening out previously-used values. Here's an example of random selection constrained to produce five unique selections from a list of fifteen words:
To explain this technique as clearly as possible, we'll first discuss a simpler form of constraint than what you see above--constraint against only a single repetition. Then we'll show how to scale the procedure up.
Here's how to achieve a simple, first-order constraint. First, we initialize a pair of variables to the same value:
var randy = 0;
var randyOld = 0;
In ActionScript as in JavaScript, it's possible to place certain statements inside control structures such as loops and functions so that they can be repeated on command. The statements above must be placed outside any such structures and be executed only once, when the movie loads. In the example above they are placed within an onClipEvent(load) handler attached to the Scripts Movie Clip. You'll see why this placement is important in just a moment.
The first variable, randy, holds the current random value. The other variable, randyOld, is used to store the random value generated on the previous run of the function.
Needless to say, when the movie is loaded there has been no previous run, so we have to supply initial values. It's essential that both variables be assigned the same value. Again, you'll see why in just a bit.
Next we make a change to the statement that generates the random number randy. In the unconstrained version of the function, that statement is:
randy = Math.floor(Math.random()*contentArray.length);
In the constrained case, however, we place this statement within a special construction called a while loop:
while(randy == randyOld)
{
randy = Math.floor(Math.random()*contentArray.length);
}
A while loop executes so long as its conditional clause evaluates to true. In this case, so long as the random number we generate is the same as the random number we previously generated, we generate a new random number. In other words we keep trying numbers until we hit one that is not the same as the one that came up previously.
This is why both randy and randyOld must have the same value on the first run of the function: we only get a random value if the two variables are identical.
One more refinement makes the constraint complete. Outside the while loop we add this statement:
randyOld = randy;
This statement records the current random number and stores it in the variable that will be used for comparison on the next run of the function. This line lets the function remember its previous behavior each time through.
Extensions of ConstraintUsing the logic explained above, you may constrain a random number generator against several orders of repetition, so that it is guaranteed to produce non-repeating values for three, four, five, or more successive iterations. The crudest way to do this is simply to create more storage variables (randyOlder and randyOldest, for instance), write a compound test condition for the while loop, and push every new random value back through the record variables as we go.
If you look at the scripts attached to the Scripts Movie Clip in the demonstration movie above, you'll find five constraint variables. That's not a very elegant solution, but you may find it easier to take in at a glance than some of the alternatives.
After the fifth level of constraint, brute-force methods may become too cumbersome for most people's tastes. It's awkward to write a test condition with six or seven parallel cases. At this point you might want to use an array instead of separate variables to store the record values. This means writing code to scan that array. Alternatively you could write previous random values to a string, moving each value one place back as it ages out; but again, you'd have to write code to look for values in that string.
Practically speaking, if the range of content choices is large enough, there may be no reason to constrain the randomizer against more than two or three repetitions.
Better SolutionsThe method we've just discussed has important flaws--executed on a very slow system it can behave sluggishly if the system randomly selects the same number many times in a row. Real programmers have better ways of constraining random number generation; unfortunately, these methods are hard to explain to people (like me) who are mathematically challenged.
The scheme described above should work fine for Flash movies for two reasons: first, Flash is very well integrated with PC operating systems so it makes excellent use of processing resources; second, most PCs today have plenty of computing power to spare for tasks like multimedia.
So unless you have a deep dislike for sloppy solutions, you may use this method with random abandon.
The Deprecated random() FunctionIf you used ActionScript in its earlier iterations (Flash 3) you may have encountered a simpler random() function. Given an argument N, this function would return an integer between 0 and N-1, inclusive. It wasn't necessary to use Math.floor() or Math.ceil().
Macromedia has officially deprecated the old random function, partly (we guess) because it is not consistent with the way people learn to code in Java and JavaScript, and partly because floor and ceiling functions allow greater control.
Though it's simpler to write, do not include the old random function in your code. You should never use deprecated commands when you can avoid them. Though Macromedia is very generous about legacy code, once an instruction is deprecated it need no longer be supported. Some future version of Flash will refuse to recognize the old random function.
Source FilesThe five demonstration movies that appear on this page are called random1.fla, random2.fla, random3.fla, random4.fla, and random5.fla. They're available on Crow within MMShare/randoms. In each movie the scripts are attached to the Scripts Movie Clip.
