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 always use capitals.
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.)
Often, however, we want to prevent any value from being chosen twice in succession. To achieve this goal, we first need to track random values, so that we can compare any value generated on a subsequent iteration of the program to the value generated on the previous iteration. Thus along with randy we also use the variable randyOld to store a previous value for comparison.
Now things get a little strange. To eliminate repetitions, we need to check every random number against its predecessor. But the first time we run the script, there is no predecessor. That is, unless we assign one, using the onClipEvent(load) handler:
onClipEvent(load){
randy = 0;
randyOld = 0;
}
We use zero here arbitrarily. So long as both variables are equal, you can assign them any value you like.
We use zero here arbitrarily. So long as both variables are equal, you can assign them any value you like.
Armed with this recording system, we can rewrite the random number generator to screen out repetitions. The new code looks like this:
onClipEvent(mouseUp){
randyRange = 10
randy = Math.floor(Math.random()*randyRange);
if(randy == randyOld){
rangeA = randyRange-randy;
rangeB = randy-1
if((rangeA > rangeB) || (rangeA == rangeB)){
randy = Math.ceil(Math.random()*rangeA)+randy;
}
else{
randy = Math.floor(Math.random()*rangeB);
}
}
randyOld = randy;
}
Given a specified range (which could have been assigned in the onClipEvent(load) handler, by the way), this script generates a random number on that range and then checks for repetition. If the value it just generated randy matches its previous output randyOld, then it assigns values to two variables, rangeA and rangeB. The first is the number of values greater than the current random value, while the second is the number of values lower than the current random.
Next we ask which range is larger, or if the two are equal. If one range is larger than the other, we want to select our new random value from the larger range, so as to maximize possibilities. We do that by adding randy (the current random value) back to the range, then using the ceil or ceiling function instead of floor so that the new numbers selected will always be greater than the current random, which we want to avoid.
If both ranges are the same size, we arbitrarily choose the range of higher numbers. If the lower range is larger, we use it.
Finally, we assign to the record variable randyOld the new value of randy we just generated, so that we can test the next random candidate against it.
The Deprecated random() FunctionIf you used ActionScript in 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 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 scripts. You should never use deprecated commands when you can avoid them. Though Macromedia is very generous about legacy code, once an instruction is deprecated there is no requirement to support it. Some future version of Flash will refuse to recognize the old random function.
