Recipe 1.11.
Repeating an Operation Many Times
Problem
You want to perform some task multiple times
within a single frame.
Solution
Use a looping statement to perform the same
task multiple times within a single frame. For example, you can use
a for statement:
for (var i:int = 0; i < 10; i++) {
// Display the value of i.
TRace(i);
}
Discussion
When you want to execute the same action (or
slight variations thereof) multiple times within a single frame,
use a looping statement to make your code more succinct, easier to
read, and easier to update. You can use either a while or a
for statement for this purpose, but generally a for
statement is a better choice. Both statements achieve the same
result, but the for statement is more compact and more
familiar to most programmers.
The syntax of a for statement consists of
five basic parts:
The for keyword
-
Every for statement must begin with a
for keyword.
Initialization expression
-
Loop typically employs an index variable
(a loop counter) that is initialized when the statement is
first encountered. The initialization is performed only once
regardless of how many times the loop is repeated.
Test expression
-
The loop should include a test expression that returns either
true or false. The test expression is evaluated
once each time through the loop. Generally, the test expression
compares the index variable to another value, such as a maximum
number of loop iterations. The overall expression must evaluate to
TRue for the for statement's body to execute
(contrast this with a do...while loop, which executes at
least once, even if the test expression is false). On the
other hand, if the test expression never becomes false,
you'll create an infinite loop, resulting in a warning that the
Flash Player is running slowly.
Update expression
-
The update
expression usually updates the value of the variable used in the
test expression so that, at some point, the conditional test
becomes false and the loop ends. The update expression is
executed once each time through the loop. An infinite loop is often
caused by failing to update the appropriate variable in the update
expression (usually the same variable used in the test
expression).
Statement body
-
The statement body is a block of
substatements enclosed within curly braces that is executed each
time through the loop. If the test expression is never
true, the for statement's body isn't executed.
The for keyword should come first, and
it should be followed by the initialization, test, and update
expressions enclosed within parentheses. Semicolons must separate
the three expressions from one another (although the
initialization, test, and update statements are optional, the
semicolons are mandatory). The remainder of the for loop is
made up of the statement body enclosed in curly braces:
for (initialization; test; update) {
statement body
}
Here is an example of a for statement
that outputs the numbers from 0 to 999:
for (var i:int = 0; i < 1000; i++) {
trace(i);
}
trace ("That's the end.");
To understand the for statement, you can
follow along with the process the ActionScript interpreter uses to
process the command. In the preceding example, the for
keyword tells the interpreter to perform the statements within the
for loop as long as the conditional expression is
true. The process is as follows:
-
The initialization expression is executed only
once, and it sets the variable i to 0.
-
Next, the interpreter checks the test expression
(i < 1000). Because i is 0, which is less than
1,000, the expression evaluates to true and the trace(
) action within the for statement body is executed.
-
The ActionScript interpreter then executes the
update statement, in this case i++, which increments
i by 1.
-
The interpreter then repeats the process from
the top of the loop (but skipping the initialization step). So the
interpreter again checks whether the test expression is
TRue and, if so, executes the statement body again. It
then executes the update statement again.
This process repeats until the test expression
is no longer true. The last value displayed in the Output
window is 999 because once i is incremented to 1,000, the
test expression no longer evaluates to true and the loop
comes to an end. Once the loop terminates, execution continues with
whatever commands follow the loop.
Both the initialization and update expressions
can include multiple actions separated by commas. You should not,
however, use the var keyword more than once in the
initialization expression. The following example simultaneously
increments i, decrements j, and displays their
values in the Output window:
for (var i:int = 0, j:int = 10; i < 10; i++, j--) {
trace("i is " + i);
trace("j is " + j);
}
|
The preceding example is not the same as two
nested for statements (which is shown in the next code block.)
|
|
It is also common to use nested for statements. When you
use a nested for statement, use a different index variable
than that used in the outer for loop. By convention, the
outermost for loop uses the variable i, and the
nested for loop uses the variable j. For
example:
for (var i:int = 1; i <= 3; i++) {
for (var j:int = 1; j <= 2; j++) {
trace(i + " X " + j + " = " + (i * j));
}
}
The preceding example displays the following
multiplication table in the Output window:
1 X 1 = 1
1 X 2 = 2
2 X 1 = 2
2 X 2 = 4
3 X 1 = 3
3 X 2 = 6
It is possible to nest multiple levels of
for statements. By convention, each additional level of
nesting uses the next alphabetical character as the index variable.
Therefore, the third level of nested for statements
typically use k as the index variable:
for (var i:int = 1; i <= 3; i++) {
for (var j:int = 1; j <= 3; j++) {
for (var k:int = 1; k <= 3; k++) {
trace(i + " X " + j + " X " + k + " = " + (i * j * k));
}
}
}
Additionally, you can use for statements
to loop backward or to update the variable in ways other than by
simply adding or subtracting one:
// Count backward from 10 to 1.
for (var i:int = 10; i > 0; i--) {
trace(i);
}
// Display a sequence of square roots.
for (var i:Number = 50000; i > 2; i = Math.sqrt(i)) {
trace(i);
}
In this case, the variable i winds up
holding values other than integers, so it is best to declare it as
a Number rather than
an int.
|
You should not use a for statement to
perform tasks over time.
|
|
Many programmers make the mistake of trying to
use for statements to animate sprites; for example:
for (var i:int = 0; i < 20; i++) {
_sprite.x += 10;
}
Whereas the preceding code moves the sprite 200
pixels to the right of its starting point, all the updates take
place within the same frame. There are two problems with this.
First, the Stage updates only once per frame, so only the last
update is shown on the Stage (causing the sprite to jump 200 pixels
suddenly rather than moving smoothly in 20 steps). Second, even if
the Stage updates often, each iteration through the for loop
takes only a few milliseconds, so the animation would happen too
quickly. For actions that you want to take place over time, use the
enterFrame event (see
Recipe
1.5) or a timer (see Recipe
1.12).
Moreover, tight repeating loops should not be
used to perform lengthy processes (anything that takes more than a
fraction of a second). The Flash Player displays a warning whenever
a single loop executes for more than 15 seconds. Using the other
methods (just mentioned) avoids the warning message and allows
Flash to perform other actions in addition to the repeated actions
that are part of the loop.
See Also
Recipes 1.5
and 1.12.
The for statement is used in many practical situations, and
you can see examples in a great many of the recipes throughout this
book. See Recipe
5.2 and Recipe
12.8 for some practical examples. Recipe
5.16 discusses for...in loops, which are used to
enumerate the properties of an object or array.
|