An Example
In this lesson we'll be using arrays and a neat new "Math" method to display random quotes. The quotes are put in an array and displayed with "document.write()". The quote to write is selected randomly by using JavaScript's "Math.random()" method.
Here's an example. The example loads a different quote each time the page is loaded. Try reloading it a few times and watch the quote change. I've only got ten quotes in the array, so you may see some repeats.
We'll start this project by making the array of quotes. You should be familiar with this:
<script language="JavaScript">
quoteList = new Array();
quoteList[0] = "Code Punk is all good.";
quoteList[1] = "Deer are tasty as well as cute.";
quoteList[2] = "Mules are stubborn.";
...
quoteList[9] = "See how this works?";
</script>
This is a pretty straightforward array. To display a randomly selected quote we'll use "document.write()" in the <body>.
<script language="JavaScript">
document.write(quote);
</script>
The only thing to notice in the display code is the use of the variable "quote". This putting a random quote from our array into this variable is what we'll be figuring out in this lesson.
Making A Random Number
Computers cannot generate truly random numbers. They're not like people. We can just come up with any number from a range of numbers anytime. Computers make "pseudo-random" numbers that are generated by running a "seed number" through a complex algorithm. The results look like this.
Click the above link again and you'll notice that the number changes to another random number. Cool, huh. The box above was made with the following link:
<a href="javascript:alert(Math.random())>
It's the "Math.random()" part that generates the pseudo-random number. Note: I'll be using "random" to refer to "pseudo-random" numbers in the future. Be sure you understand that computers cannot generate truly random numbers.
Seeding
You can use a plain "Math.random()" every time you need a random number. In practice, however, the method is usually given a "seed number" in the parentheses. This is the number that is run through the randomization algorithm:
Math.random(8)
This just runs the number 8 through the algorithm. Seeding with a constant number, or no seed number at all, can lead to recurring results. This should be avoided as the whole purpose of randomization is to produce unpredictable results.
To get around this you can use a constantly changing number to seed your "Math.random()". One favorite is the seconds from a Date() object.
now = new Date();
seed = now.getSeconds();
var random_number = Math.random(seed);
The above provides a new seed number every second. This makes for good (unpredictable) randomization. The variable "random_number" will now hold the generated random number.
For our current example, such a seeding process isn't really needed. We're only using one random number one time (each time the page loads). If you needed either more random numbers or a dynamically changing random number, you should use some method to make sure the seed number constantly changes. You can use one random number to seed another.
I strongly recommend using a dynamically changing seed number right from the start so you'll be used to it.
Setting The Range
You've probably already started wondering about how to get all of those numbers to the right of the decimal point to represent the range of whole numbers you need to use for your program. In our example, we need to produce the numbers 0-9.
Two simple tools that we already know will do this for us. To set the range of numbers, we just multiply the random number by the number of random choices we want to make. Our array has ten objects, so we'd just multiply the random number by 10.
The second thing we need to do is to round the number with "Math.round()" to remove the numbers remaining to the right of the decimal point. Rounding causes a few quirks we'll discuss in the next section. As an alternative, you could use Math.floor() or parseInt() which just drop the numbers to the right of the decimal point.
Back to multiplying to set our range. We want a range of ten numbers beginning at 0 and ending with 9. To do this we'd just multiply our random number by 10:
now = new Date();
seed = now.getSeconds();
var random_number = Math.random(seed);
var range = random_number *10;
I've added a new variable called "range" to hold the product of the "raw" random number multiplied by 10. Remember that the raw random number is several digits all to the right of the decimal point. Multiplying by 10 moves the first number to the left of the decimal point.
Say our "random_number" equalled .4062... Multiplying by 10 gives us 4.062... The overall range of numbers to the left of the decimal point will now be the 0 - 9 we were looking for. Multiplying by 100 would give us options from 0 to 99, and so forth.
This works for all ranges, not just multiples of 10. Say you want only two random options. You'd just multiply the random number by 2. When the first number to the right of the decimal point is 4 or less, you'll get a zero to the left of the decimal point. If it's five or more, you'll get a one.
Simple multiplication works for any range of numbers. Just multiply by the raw random number by the range of options you want to select from. When determining your range, don't forget to include the first and last numbers of your range. There are six, not five, numbers between 3 and 8 if the 3 and 8 are both included.
If you look at the source code for the example, you'll notice I didn't use a multiple of 10 even though that would work. Instead I used "quoteList.length":
var range = random_number * quoteList.length;
This way I can add quotes to the array without having to go back over my randomization formulas. This will insure that the raw random number is always multiplied by the number of objects in the array.
Rounding
Now we need to round our random number to get rid of the remaining numbers to the right of the decimal point. This starts out really easy:
now = new Date();
seed = now.getSeconds();
var random_number = Math.random(seed);
var range = random_number * quoteList.length;
var rounded_number = Math.round(range);
I've just made a new variable called "rounded_number" and used "Math.round()" to round our "range" number. Remember that "Math.round()" will round our number to the left of the decimal point up if the value to the right of the decimal point is .5 or higher. It rounds down, or just ignores the numbers to the right of the decimal point, if they are less than .5.
This rounding can cause problems. First lets look at the high-end problem. Imagine that our raw random number is .9857... We multiply by 10 to get 9.857. When we run this number through "Math.round()" we get 10!
We don't have a "quoteList[10]" and will receive an error. This error is due to the rounding process and occurs fairly frequently -- 1 out of 20 times. Not something you'd want to ignore.
Another problem occurs at the lower end of our range. Getting a 0 will occur only half as often as the other numbers due to rounding. Think about it. The other numbers have a 1 in 10 chance of being selected because they can be rounded "up to" or "down to". Zero can only be rounded "down to". This means it will be selected half as often as the other numbers.
You can only get a 0 if the first number of the raw random number is a zero (1/10 chance) and the second number is 0 - 4 (1/2 chance) or a total of a 1/20 chance.
Given the above two problems we can come up with an easy solution for both. We can use an IF statement to detect when the high-end problem occurs and then set our random number to equal zero, giving the chances of zero occuring a boost.
Here's this solution in action. Notice that I again use "quoteList.length" instead of a constant number. This is so I can add a quote to the array without having to redo my math:
now = new Date();
seed = now.getSeconds();
var random_number = Math.random(seed);
var range = random_number * quoteList.length;
var rounded_number = Math.round(range);
if (rounded_number == quoteList.length){rounded_number = 0}
This neat little workaround will detect when our rounded number goes out of bounds and set it to zero when it does. This solves both of our rounding problems.
Now that we've got a random number we can use with our array, all we need to do is assign it to our "quote" variable used in the "document.write()":
now = new Date();
seed = now.getSeconds();
var random_number = Math.random(seed);
var range = random_number * quoteList.length;
var rounded_number = Math.round(range);
if (rounded_number == quoteList.length){rounded_number = 0}
var quote = rounded_number;
Now we're finished. Put all the pieces together and you've got a random quote generator. You can put the quotes anywhere in your page, style them, and add a quote just by adding another object to the array -- no more math.
Ranges Not Beginning With 0
When making random selections from an array, you'll almost always want to your range of numbers to begin with zero. This may not always be the case. Say we wanted to randomly select numbers between 12 and 18 (including 12 and 18).
No problem. Just calculate the range between the numbers. Remember to include the beginning and ending numbers of the range. In this case the range would be 7. Use this as the multiple.
After the number has been rounded and the randomization complete, just add the number at the lower end of the range -- 12 in our case. This addition will push the range from 0 to 6 to 12 to 18.
Summary & Exercises
A lot was covered in this lesson. Don't get confused about using "Math.random()". It's not all that tough, but it takes a little practice to get a feel for it.
Make a random number by using "Math.random()" with a seed number in the parentheses.
To get useful numbers, first multiply the raw random number by the number of options you need, like the number of objects in an array.
Eventually you'll need to round your random number to use it with an array. Use "Math.round()" and an IF statement to keep things in bounds.
Again, this was a tough lesson. Go over the material a few times and code the example step-by-step. You'll notice that in the example that I combined steps. I don't suggest doing this until you can code the effect successfully one step at a time. Then combining steps will make more sense.
Once you think you've figured this out, try making an array of image file paths and create an random image slideshow.
To Next Advanced JavaScript Lesson
Back To Advanced JavaScript Index
|