Scythe here. I’d like to give my thanks to Kirupa and Scott for writing that excellent tutorial on random numbers in Flash. I’d like to build on that a little bit with a few extra tricks. In this tutorial I will show you how to work with random numbers more extensively in AS3.
I cannot emphasize enough how important random numbers are to things such as game programming. Practically every game out there is going to have some random element to it. This is done to keep it interesting so that the player never knows what to expect, and most games use them quite a lot. Other programs besides games use random numbers too for things like graphical effects. Even kirupa.com was meant to generate a random icon at the top next to the site name, but that ended up not working out.
Random numbers come in all shapes and sizes, of course. And while random integers are some of the most common types of random numbers you’ll probably want to generate, there are some situations where you’ll want a different pattern of randomness.
Consider the following example:
This example contains six buttons that each generate random numbers in a different way, and this barely even scratches the surface of how many possibilities there are.
In this tutorial, you will see how to create these variations.
Let’s look at the formula from the other tutorial:
- Math.floor(Math.random() * (1 + High - Low)) + Low;
This is used for generating random integers, as you probably remember. In order to expand on it a little bit, we can perhaps look at this another way:
- Math.floor(Math.random() * Range) + Low;
I have replaced (1 + High - Low) with the word Range. What I’m getting at here is that when you multiply by one plus the maximum number minus the minimum number, you’re really multiplying by the amount of different integers you want your expression to be able to generate. For example, if the highest number you want to get is 7 and the lowest number is 5, you’re looking at 3 possible numbers: 5, 6, and 7. So 3 is your range, and you can also get that number with 1 + 7 – 5, as seen in that formula from before.
The reason I’m changing the formula is that, in the cases we’ll be looking at, the high and low numbers won’t be so well defined or even relevant, so you’ll need to think of it in terms of how many different possible numbers you want to be able to generate. Let’s go back a bit and say you don’t want to generate integers at all. Well that’s easy; all you have to do is take out the Math.floor():
- Math.random() * Range + Low;
Random non-integers are especially useful for random locations, random rotations, random sizes, etc. In the example from the beginning the button labeled "Not rounded" generates a random number from 0 up to, but not including, 100. Since my low number is 0, I can leave that part out and just put:
- Math.random() * 100;
Since Math.random() can equal 0, Math.random() * 100 can equal 0, because 0 * 100 = 0. But Math.random() can’t quite go all the way to 1 so Math.random() * 100 can’t quite go all the way to 100: just to 99.999, or thereabouts. Before when we were generating random integers, there were a finite number of different integers we could generate. But now that we’re allowing for random numbers between integers, there’s practically no limit to how many different numbers we can get.
But if the range is how many possible numbers you want to be able to generate, how does the range apply when there are an infinite number of possibilities, as there are in this case? Let’s take Math.random() * 3 for example:
Even though there are unlimited possibilities, they all fall within the range of 0 to 3, but remember that 0 is included and 3 isn’t. In the picture, you’ll notice 3 blue boxes. Each box represents all the numbers in between one integer and the next, i.e. the space or distance between them. So the range is 3 because it spans across 3 integer-distances, even though you’re able to generate more numbers than just the integers themselves.
The Spacing Formula
But this is all too simple, right? We’ve taken a step back from generating random integers, so let’s take a step forwards and bring back Math.floor(). But this time we’ll be more particular about the integers we generate. Rather than generating just any random integer from 0 to 100, let’s generate only odd numbers:
- Math.floor(Math.random * 50) * 2 + 1;
Now we’re using multiplication twice: once before applying Math.floor(), and once after. The number that we’re multiplying before is still the range, same as ever. We’re multiplying by 50 because half of all integers are odd, and there are 100 integers from 0 up to but not including 100, and half of 100 is 50. Then we’re multiplying by 2 because odd numbers only show up every other integer, so they’re twice as spread out. Finally we add 1 since that’s our low number. The lowest odd number from 0 to 100 is 1.
This might seem confusing, so let me show this as a formula:
- Math.floor(Math.random * Range) * Spacing + Low;
This is the formula for whenever you want to generate random numbers from a finite, evenly spaced set. All the odd numbers from 0 to 100 is such a set. It’s finite because you know how many of them there are: 50. And it’s evenly spaced because you know that all odd numbers are 2 numbers apart: 2 integer-distances away from each other. Generating even numbers from 0 to 100 is exactly the same as generating odd numbers except that the low number is 0. If you want to generate multiples of 3, just use 3 for the spacing. You can do the same for multiples of 5, or 15, or anything. Just make sure you know what your range is.
But what if the spacing is a fraction? Also, what if you want to generate random non-integers, but want control over what they’re rounded to? These questions have the same answer, actually.
If you want your random numbers to include only certain non-integers, say multiples of one half, you can just include one half as your spacing. This works because the spacing is multiplied after Math.floor() is applied, so it isn’t rounded off to an integer. Since multiplying by one half is the same as dividing by 2, your expression would look like this:
- Math.floor(Math.random * 200) / 2;
The range is 200 because there are twice as many possible numbers between 0 and 100 than there are integers if you include halves. For every integer, there’s that integer and a half, like 5 and a half for example. The low number is 0 so that’s left out. If you want to round to the nearest tenth, use one tenth as the spacing, which means you’d be dividing by 10. You can round off to anything like this.
Left or Right
Let’s look at another application of this spacing formula and say you want something to move either to the left or to the right, but not stand still. If you click on the “Left or right” button in the example from the beginning, the current number will either have 1 added to it or subtracted from it, much like you’d do to a display object’s x property if you wanted it to move left or right. This is accomplished by generating a random number from -1 to 1 that doesn’t include anything in between.
So what do you think the range is? Since there are only 2 possibilities, the range is 2. Also since -1 and 1 are 2 spaces apart from each other, the spacing is also 2. And finally the low number is -1, so the expression looks like this:
- Math.floor(Math.random() * 2) * 2 – 1;
See how easy that was? I’m surprised myself, actually.
Finally, what do you do if you want to generate random numbers from a
set that isn’t evenly spaced, or even one that doesn’t have any
discernable pattern at all? This was actually covered in
one of Kirupa’s tutorials, but I’ll cover it just the same.
All you have to do is generate a plain old ordinary everyday random integer, and then use that integer as an index for an array. Let’s say you have an array of prime numbers that looks like this:
- var primes:Array = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29];
You can access one of the array’s elements at random like this:
- primes[Math.floor(Math.random() * primes.length)];
The range is the length of the array since that’s how many possibilities there are, and the low number is 0 since array indices are zero-based in AS3. Keep in mind that you can do this for any array, even one that doesn’t contain numbers at all.
One last thing to note is that you can always use int() instead of Math.floor(), for any of this. It yields exactly the same results as long as you don’t multiply Math.random() by a negative number. Not only is int() faster to type, Math.floor() takes 15 times longer to run according to my tests. But it’s rare that you’ll have to worry about simple functions like these slowing down your programs.
And that’s what I have to say about that. You can download the source file if you like:
I hope you were able to understand at least half of my jargon, but thanks for reading either way. And definitely check out the forums for assistance. Scythe… out.
|Kyle Delaney (Scythe)|