Expand and apply your knowledge of programming logic by learning about counting loops, nested loops, and sentinel loops.
Published: April 13, 2007
Last updated: September 10, 2007
By Richard G. Baldwin
Alice Programming Notes # 175
This tutorial lesson is part of a series designed to teach you how to program using the Alice programming environment under the assumption that you have no prior programming knowledge or experience.
Have some fun
Because Alice is an interactive graphics 3D programming environment, it is not only useful for learning how to program, Alice makes learning to program fun. Therefore, you should be sure to explore the many possibilities for being creative provided by Alice while you are learning to program using these tutorials. And above all have fun in the process of learning.
In the lesson titled "Sequence, Selection, and Loop Structures" (see Resources), I taught you about:
In the lessons titled "Relational and Logical Operators" and "Expressions and Operators" (see Resources), I taught you about the following operators:
The backbone of programming logic
Relational and logical operators, when combined with selection and loop structures, form the backbone of programming logic. It doesn't matter whether you are writing an interactive graphics game program using Alice or writing the code for an auction site on the web using Java or C#, programming logic is the most important aspect of the program. Programming logic is what separates a computer from more mundane programmable devices such as VCR recorders.
In this lesson...
In this lesson I will help you to expand and apply your knowledge in this area by teaching you about some very specific loop structures:
Along the way, I will also teach you about the following operators:
I recommend that you open another copy of this document in a separate browser window and use the following links to easily find and view the figures and listings while you are reading about them.
Once you have mastered Alice, I recommend that you also study the other lessons in my extensive collection of online programming tutorials. You will find a consolidated index at www.DickBaldwin.com.
What is a counter loop?
The name counter loop results from the fact that a loop of this type runs an incremental counter and continues looping until the value of the counter reaches or exceeds a pre-specified limit. The counter may increment by a value of one or by a value of more than one, but it increments by the same amount each time it increments.
This lesson illustrates two forms of counter loops. One form is implemented using a while loop. A sample program is provided that illustrates the use of a while loop to implement a counting loop.
The other form is implemented using a for loop. Three sample programs are provided that illustrate the use of a for loop to implement a counting loop.
What is a nested loop?
The name nested loop results from the fact that it consists of two or more loop structures nested inside one another.
This lesson illustrates the use of one for loop nested inside another for loop. Each of the for loops run an incremental counter and uses the value of the counter to determine when to stop looping.
What is a sentinel loop?
A sentinel loop is a loop that continues looping until some value (the sentinel) matches a predefined value. Let me explain the concept of a sentinel loop by using an example. Suppose I want to write a program that I can use to compute the average of a set of student grades. Each time I run the program, the number of grades in the set is likely to be different.
I can write the program such that I can sequentially enter all of the grades in the set followed by a so-called sentinel value. The program will continue reading, adding, and counting grades until I enter the sentinel value. When I enter the sentinel value, the program will recognize that all of the grades have been entered and will compute and display the average of all the grades in the set.
This is the scenario for which the program named Alice0175f was designed.
The sentinel value
The sentinel value must be chosen carefully to ensure that it won't be confused with a valid data value. In the case of grades, a good value for a sentinel value would be -1, since I never award negative grades to students.
I will present and explain six different Alice programs in this lesson. Each program illustrates one of the loop structures in the above list.
Let me begin by saying that ordinarily I wouldn't use a while loop to implement a counting loop. Instead, I would use a for loop.
However, since you already know about while loops and don't yet know about for loops, I decided to begin with a while loop in order to be on familiar ground. My hope is that a comparison of this program with the three programs that follow will make it easier for you to understand some of the subtleties of the more cryptic for loop used in those programs.
The source code for this program is presented in Listing 1.
Request for user input
The program begins by asking the user to enter an integer between 1 and 5 inclusive producing the screen dialog shown in Figure 1.
Figure 1. Request for user input in the program named Alice0174a.
The variable named limit
This integer is stored in the variable named limit, which will be used in the conditional clause of a counting while loop. The loop will count from zero to one less than the value entered by the user, executing the body of the loop once for each count. The program will display a penguin during each iteration through the body of the loop as shown in Figure 2.
Figure 2. Program named Alice0174a while running.
The variable named index
Listing 1 also declares a counting variable named index. The initial value of index is immaterial because its value is set to 0 immediately before the execution of the while loop.
The increment operator
The index value is incremented (increased) by a value of one at the end of the code in the body of the loop using an increment operator (++).
This is an operator that I haven't previously explained. The increment operator is a unary operator, meaning that it has only one operand. When the increment operator follows the name of a variable (postfix configuration), a value of 1 is added to the current value stored in the variable.
Begin with an index value of zero and count upward
The value of the index variable is zero the first time it is tested in the conditional clause of the while loop.
As a result of incrementing the index variable at the end of each execution of the body of the loop, the value of index will have been increased by one each time it is tested against the value of limit in the conditional clause of the while loop.
The loop structure continues to execute the code in the body of the loop for as long as (while) the value of index is less than the value of limit. When the value of index becomes equal to (or exceeds, which is impossible in this program) the value of limit, the body of the loop is skipped and control transfers to the code following the loop.
The final screen output
The code following the body of the loop produces the screen output shown in Figure 3. The number of penguins showing will depend on the value entered by the user in Figure 1.
Figure 3. End of run for program named Alice0174a.
Nested if-else constructs
Although the code in the body of the loop appears to be rather complicated, it is actually fairly simple. The main portion of that code consists of multiple nested if-else constructs similar to those that you learned about in the earlier lesson titled "Sequence, Selection, and Loop Structures" (see Resources). The purpose of the nested if-else constructs is to determine the current value of index and to cause a particular penguin associated with that value to become visible on the screen for each integer value of index.
Would prefer to use an equality test
Normally, we would prefer to use a test for equality in the conditional clause of the if statement. However, there is a problem with doing that in Alice. Alice has only one numeric type named Number and it is not an integer type. Therefore, the value of index can have a fractional part. Although none of the code that we have written would be expected to produce a fractional part, general accuracy problems can result in very small fractional parts. As a result, testing two values of type Number for absolute equality is highly unreliable and will often result in a false result even though the two values are equal for all practical purposes.
In order to overcome this problem, the conditional clauses in the if statements in Listing 1 test the value of index to determine if it is less than a value that is half way between two integer values instead of testing for absolute equality with a given integer.
When the test returns...
When the test in the if-else clause returns true, an image of a specific penguin is displayed. When the test returns false, the else clause containing the next if statement in the nested structure is executed to test for the next value of index. (Note that there is an easier way to do this using an array or a list, which is the topic of a future lesson.)
When user input values are out of range
Although requested to do so, there is no requirement for the user to enter an integer value between 1 and 5 inclusive. The user can enter any value including fractional and negative values.
If the user enters a value of zero or a negative value, the body of the loop is never executed and no penguins are displayed.
If the user enters a value greater then five, the else clause containing the term Do Nothing is executed during each iteration of the loop, and only five penguins are displayed, no matter how large the value entered by the user.
This program was designed to be as simple as I could make it and still use a for loop to produce some meaningful output.
A complete listing of the source code for the program is shown in Listing 2.
Briefly, the program uses a for loop to count from 0 to 5 inclusive
and displays the value of the count during each iteration of the loop as shown
Figure 4. Program named Alice0174b while running.
When the conditional clause returns false...
When the upper limit of 5 has been reached, the conditional clause returns false, the body of the loop is skipped, and a single statement following the for loop is executed producing the screen output shown in Figure 5.
Figure 5. End of run for program named Alice0174b.
Explanation of the source code
Now consider the source code shown in Listing 2. Note first that this program does not declare and initialize a variable named index as was the case for the while counting loop shown in Listing 1. Note also that the body of the loop does not contain a statement to update the index as was the case for the while counting loop shown in Listing 1.
Creating a for loop template
To create a for loop, you drag the loop tile from the bottom of the Alice development screen and drop it into the appropriate location in the edit pane. When you do that, you will be required to specify the number of times that the body of the loop is to be executed. (You can replace this value with an expression or variable name later.) Then the template shown in Figure 6 will appear in the edit pane.
Figure 6. Basic template for a for loop in Alice.
Interpretation of the template
You can interpret the template in Figure 6 to mean that the body of the loop will continue to be executed for as long as the value of index is less than 6 (or whatever value or expression you elect to insert there).
The important thing to note about the template for the for loop is that it contains three clauses surrounded by parentheses and separated by semicolons:
The counter declaration and initialization clause
This clause consists of everything between the left parentheses following the word for and the first semicolon. This is a particularly interesting clause, which:
The type named int
It is very interesting that the type int is used here. Normally, Alice does not support type int, although it is supported in other languages such as Java, C++, and C#. The type named int in those languages is a true integer type with no fractional parts allowed. Since Alice was actually written using the Java programming language, it is probably safe to assume that int is also a true integer type in Alice when it is available.
Type int is not normally available to the Alice programmer
When you declare a numeric variable in Alice, you are not allowed to declare the type of your variable as type int. Your only choice for numeric data is type Number, which is not an integer type. I strongly suspect that the folks on the Alice development team took the unusual step of using type int in this case to prevent the for loop from suffering from the problems that occur with a conditional clause that tests for absolute equality between two variables of type Number.
Not necessary to declare and initialize a counter variable
In any event, the existence of this clause is the reason that it was not necessary to declare and initialize a counter variable in Listing 2 as was the case in Listing 1. With a for loop in Alice, the counter variable is automatically declared and initialized as part of the template for the loop structure.
The conditional clause
The conditional clause in a for loop is essentially the same as the conditional clause in a while loop or in an if-else construct.
The counter update clause
The counter update clause appears in Figure 6 after the second semicolon and before the closing parentheses. There are two different versions of this clause available. The version shown in Figure 6 uses an increment operator identical to the one that I used in the counter update statement at the end of the body of the while loop in Listing 1. This clause serves the same purpose as that statement serves in Listing 1. In particular, it adds a value of one to the counter variable before transferring control back to the conditional clause for the next test.
When are the three clauses executed?
Even though all three clauses are physically located in the header of the for loop, that isn't necessarily when and where they are executed.
The counter declaration and initialization clause
The counter declaration and initialization clause is executed once and only once when control first enters the for loop structure. After that clause is executed, control passes to the conditional clause. In Alice, the purpose of this clause is to initialize the value of the counter variable named index to zero. Once index is declared and initialized to a value of 0, this clause is never executed again (unless control leaves the loop and later returns to the same section of code).
The conditional clause
The conditional clause is executed once during each iteration of the loop immediately before the code in the body of the loop is executed. (Like the while loop, the for loop is an entry-condition loop.) If the expression in the conditional clause evaluates to true, the code in the body of the loop is executed one more time before testing the expression in the conditional clause again.
If the expression in the conditional clause evaluates to false, the body of the loop is skipped and control passes to the code immediately following the loop structure.
The counter update clause
The counter update clause is executed once during each execution of the body of the loop. However, regardless of the fact that the update clause is physically located in the loop header at the top of the loop, it is not executed until after the last statement in the body of the loop has been executed. In other words, it is executed immediately before control transfers back up to the conditional clause to make the next test.
The update clause is used to increment the counter, eventually causing the conditional clause to evaluate to false, causing the loop to terminate.
The show complicated version button
If you click the button in Figure 6 labeled show complicated version, that will change the template with respect to the counter update clause to an alternative version. The alternative version is shown in Figure 7. (Note that I purposely cropped off the left end of the statement in Figure 7 to force it to fit into this narrow publication format without a requirement to reduce the image and make it unreadable.)
Figure 7. The alternative version of the counter update clause.
The starting index value
One of the things worth noting in Figure 7 is the little triangle following the 0 on the left side of Figure 7. Clicking that triangle exposes a drop-down list that lets you specify a numeric value other than 0 as the starting value for the counter variable. In addition, in typical Alice fashion, you can specify an expression, including the name of a variable instead of a literal numeric value. Note however that the expression must evaluate to a value of type Number.
The additive assignment operator
The additive assignment operator shown in the counter update clause in Figure 7 is another operator that I haven't previously explained in this set of tutorial lessons. This operator lets you specify the amount by which the counter variable will be increased each time the counter update clause is executed. (An update value of 2 was specified in Figure 7, which will cause the counter loop to count by twos.)
Behavior of the program
The behavior of this program is the same as the behavior of the earlier program named Alice0175b except that the values displayed in the bubble shown in Figure 4 are 0.0, 2.0, 4.0, etc. instead of 0.0, 1.0, 2.0, etc. In other words, the earlier counting loop counts by ones whereas this counter loop counts by twos. The loop can be made to count by any value you choose, (including fractional and negative values), by changing the specified value in the counter update clause. Note, however, that if you specify a negative value, it may take a very long time before the conditional clause will evaluate to false and cause the loop to terminate.
The source code for this program is presented in Listing 3.
Now that you know all about the basics of for loops and counting loops implemented using for loops, you should have no difficulty understanding the code in the program named Alice0175d. A complete listing of the program is shown in Listing 4.
You should compare this code with the code for the while loop in Listing 1. Like the code in Listing 1, the code in Listing 4 counts and displays penguins as shown in Figures 1, 2, and 3. However, the for loop version in Listing 4 is simpler than the while loop version in Listing 1.
Now for something different. This program uses a pair of nested for loops to compute and display the values in a 3x5 grid of numeric values.
The screen output
There are no significant 3D images produced by this program so I won't show you any screen shots. However, I will show you the numeric output that appears on the screen in the rectangular area immediately below the area labeled World Running... Figure 8 shows the values in the 3x5 grid of numeric data produced by the program.
Figure 8. Screen output for the program named Alice0175e.
the value of world.main.rowData is 0.0 0.0 0.0 0.0 0.0 the value of world.main.rowData is 0.0 1.0 2.0 3.0 4.0 the value of world.main.rowData is 0.0 2.0 4.0 6.0 8.0
The source code for the program
The source code for this program is shown in Listing 5.
A pair of nested for loops
If you look carefully, you will notice that this program contains two different for loops, one nested inside the other.
Confusing variable names
One thing that can be confusing about this source code is that the counter variable for both of the for loops is named index. (That would not be allowed in programming languages such as Java, C++, and C#.) Note however that when the two counter variables are referenced later inside the body of the loop, they are given the following names for clarification:
That does help to clarify the situation, but only if you know that index_#2 is the counter variable for the inner loop and index is the counter variable for the outer loop.
The number of rows and the number of columns
This program declares and initializes two variables named rowLim and colLim to values of 3 and 5 respectively to represent the number of rows and the number of columns in the grid shown in Figure 8.
Similar to an odometer
The behavior of nested for loops is similar to the behavior of the odometer in your car. For example, each column of numbers in the odometer in your car cycles through the values of 0 through 9 for each one-unit change in the column to its left.
The outer for loop in listing 5 iterates on rows and the inner for loop iterates on columns. Because the value of colLim is 5, the body of the inner loop executes (iterates) five times for each execution (iteration) of the body of the outer loop. Thus the total number of iterations of the body of the inner loop is 15, which is the product of 3 and 5. (This is also the number of values shown in the grid of values in Figure 8.)
Displaying the numerical results
Listing 5 declares a String variable named rowData. This string variable starts out containing a single space character. Each time the body of the inner loop is executed, it appends a new numeric value, (which is the product of the current row number and the current column number) along with a space character onto the end of the string.
Inner loop conditional clause evaluates to false
After each set of five iterations of the body of the inner loop, the conditional clause of the inner loop evaluates to false. This causes control to pass to the statement immediately following the body of the inner loop.
The statement immediately following the body of the inner loop uses a print tile to display the string variable as one line of text in Figure 8. The statement that follows that one replaces the characters in that string with a single space character, at which time control is passed backup to the conditional clause for the outer loop.
Continue looping until...
This process continues until the conditional clause for the outer loop evaluates to false, at which time control is passed to the next statement following the body of the outer loop. Since there are no statements following the body of the outer loop, the program has nothing more to do at that point and the program terminates.
Listing 7 presents the source code for a type of loop commonly referred to as a sentinel loop.
I explained the general rationale for a sentinel loop and the rationale for this program in particular earlier.
The program declares and initializes the following working variables that are used in the algorithm:
Do a priming read
The program begins with a priming read asking the user to either enter a grade or to enter -1 to quit entering grades as shown in Figure 9.
Figure 9. Request for user input data in program named Alice0175f.
Control enters the while loop
As you can see in Listing 7, after the user responds to the priming read request and enters the first grade value, control passes into the conditional clause of the while loop.
Is the grade greater than or equal to zero?
Each time the conditional clause is executed, it tests the value of the grade to confirm that it is greater than or equal to zero. If not, the body of the loop is skipped and control passes to the code following the body of the loop. This code is executed to compute and display the average grade. (See Figure 10 and also see sidebar.)
If the grade entered is greater than or equal to zero...
If the grade entered by the user is greater than or equal to zero, the code in the body of the loop is executed. The first statement in the body of the loop adds the new grade to the sum, which was initialized to a value of zero when it was declared. Assuming the grade values that are entered are greater than zero, the value of sum increases during each iteration of the body of the loop.
Get another grade and increment the grade counter
After adding the grade to the sum, the code in the body of the loop solicits another grade from the user, producing the output shown in Figure 9 again. When the user enters the new grade (or -1), the code in the body of the loop increments the variable named count, which is keeping track of the number of actual grades entered, and transfers control back to the conditional clause at the top of the loop. The value of count was also initialized to zero when the variable was declared.
Keep on looping...
This process continues until the user enters -1, at which time the body of the loop is skipped and the two statements following the body of the loop are executed.
Compute and display the average grade
The first statement following the body of the loop divides the sum of the grades by the number of grades to compute the average. The next statement causes the average grade to be displayed as shown in Figure 10. This display stays on the screen for five seconds and then the program terminates.
Figure 10. Report of average grade in program named Alice0175f.
The average grade could also have been displayed using a print tile as an alternative approach.
Executable versions of the programs that I explained in this lesson can be downloaded by following the link in Resources. I encourage you to either download those programs, or copy the code from Listings 1 through 7 into your Alice development environment and run the programs. Experiment with the code, making changes, and observing the results of your changes. Create some strange results and have some fun in the process.
In this lesson I helped you to expand and apply your knowledge of programming logic by teaching you about some very specific loop structures:
Along the way, I also taught you about the following operators:
In future lessons I will teach you about:
So stay tuned. There is a lot of fun ahead.
Beginning with the program named Alice0175f, create a new program.
The behavior of the new program is the same as the behavior of the original program except that the the sentinel value can be any negative value or any value greater than 100.
Update the user input message shown in Figure 9 to make it appropriate for the new behavior of the program.
Save your world in a file named Alice175LabProjA.a2w and be prepared to deliver it to your instructor in whatever manner the instructor specifies.
Make certain that your preferences are set to Java Style in Color.
Select Export Code For Printing... on the File menu and save your source code in a file named Alice175LabProjA.html. Also be prepared to deliver this file to your instructor in whatever manner the instructor specifies.
Where is the movie?
Because of the simplicity of the animation in this project, no movie is provided.
Resources from earlier lessons in the series titled "Learn to Program using Alice"
Listing 1. Source code for the program named Alice0175a.
Created by: Dick Baldwin
Listing 2. Source code for the program named Alice0175b.
Created by: Dick Baldwin
Listing 3. Source code for the program named Alice0175c.
Created by: Dick Baldwin
Listing 4. Source code for the program named Alice0175d.
Created by: Dick Baldwin
Listing 5. Source code for the program named Alice0175e.
Created by: Dick Baldwin
Listing 6. Source code for the program named Alice0175e in Alice Style display format.
Created by: Dick Baldwin
Listing 7. Source code for the program named Alice0175f.
Created by: Dick Baldwin
Copyright 2007, Richard G. Baldwin. Faculty and staff of public and private non-profit educational institutions are granted a license to reproduce and to use this material for purposes consistent with the teaching process. This license does not extend to commercial ventures. Otherwise, reproduction in whole or in part in any form or medium without express written permission from Richard Baldwin is prohibited.
Richard has participated in numerous consulting projects and he frequently provides onsite training at the high-tech companies located in and around Austin, Texas. He is the author of Baldwin's Programming Tutorials, which have gained a worldwide following among experienced and aspiring programmers. He has also published articles in JavaPro magazine.
In addition to his programming expertise, Richard has many years of practical experience in Digital Signal Processing (DSP). His first job after he earned his Bachelor's degree was doing DSP in the Seismic Research Department of Texas Instruments. (TI is still a world leader in DSP.) In the following years, he applied his programming and DSP expertise to other interesting areas including sonar and underwater acoustics.
Richard holds an MSEE degree from Southern Methodist University and has many years of experience in the application of computer technology to real-world problems.