Lesson 4: Looping

Computer programs function by doing the same things over and over again at very high speed. This looping behavior enables the user to continue to use the program until the loop is stopped by either the program or the user. In the gaming world the faster a game program can loop the better. Gamers like this because it enables their games to have high frame rates also known as the FPS (frames per second).

FOR ... NEXT Looping

Remember the program we created in lesson 3 that used GOTO to create a loop that counted from 1 to 24? There is a much better and preferred method to create a loop that does the same thing.

The FOR...NEXT statement is used to create controlled loops. A controlled loop is one where you explicitly know the start and end values of the loop. FOR...NEXT statements can count forward or backward in any increment you wish. The default behavior for a FOR...NEXT loop is to count forward by 1 (a STEP value of 1) until the end value has been reached.

FOR Count% = 1 to 24 ' increment Count% from 1 to 24 in steps of 1

The integer variable Count% is used to hold the value of the FOR...NEXT loop. 1 TO 24 indicates the start and end values of the loop counter. The first time the loop executes Count% will contain the value of 1, the second loop execution the value of 2, and then 3, and so on. This continues until Count% finally reaches the end value of 24. This line controls when the loop ends:

NEXT Count% '          keep looping until Count% = 24

Only when the NEXT statement sees that Count% equals the ending value specified will it end the loop. All code contained within the code block between the FOR and NEXT statements is executed over and over again while the loop is active.

STEP it Up

The STEP statement may be used in conjunction with the FOR...NEXT statement to change the default direction of the count. Save the previous example as ForNext.BAS before typing in the next program and executing it.

The new statement CLS is used to clear the screen. It clears all text and graphics currently displayed.

The example program above uses two FOR...NEXT loops, one inside the other, creating what is known as a nested loop. The outer loop, Cstep%, counts from 1 TO 4 while the inner loop, Count%, counts from 0 TO 12 with a STEP value based on the current value of Cstep%.  It just so happens that counting from 0 TO 12 by any of the Cstep% values allows the loop to end on the number 12 each time because 12 is evenly divisible by the numbers 1 TO 4. However, what would happen if we use a STEP value that mathematically can't reach the ending number? If the next STEP value equals or is greater than the ending loop value, the loop is considered complete. Make the following modifications to the above code to see this in action.

Change line 15 to read:

PRINT "Counting from 1 to 12 by steps of"; Cstep%

Change line 17 to read:

FOR Count% = 1 to 12 STEP Cstep%

Now, execute the program again.

As you can see STEP will only reach the value of 12 by counting in steps of 1. Counting in steps of 2, 3, or 4 can't mathematically reach the number 12. This is important to remember when writing your programs. Save this program as StepUp.BAS before continuing on.

STEP it Down

STEP can also be assigned a negative value to allow FOR...NEXT loops to count in reverse. Type in the following code then execute it to see this in action.

Yes, I know, a pretty crude representation of a rocket launch. We'll revisit this code when graphics are introduced and spruce it up a bit.

There are three new commands in the example program above: SLEEP, _DELAY, and SYSTEM.

SLEEP puts the computer into a continuous loop for a given number of seconds which in effect stops program execution for that amount of time. If you do not specify the number of seconds to SLEEP the program will pause until the user presses a key. Also, the user can over-ride the SLEEP time at any point by pressing a key.

_DELAY (yes, the underscore is part of the command, more on that later) performs the same action as SLEEP but gives the programmer finer control over the timing. SLEEP will only work with whole seconds while _DELAY allows the programmer to specify the timing duration down to the millisecond, or thousandths of a second. _DELAY .001 would cause the program pause for one one thousandth of a second. In the program above _DELAY .1 forces the program to pause for 100 milliseconds or one tenth of a second.

SYSTEM forces the text window to close immediately once the program has finished. No "Press any key to continue" message is displayed. The program simply ends, the window is closed, and the operating system is given back control.

Go ahead and save this program as Liftoff.BAS before continuing.

DO...LOOP Looping

Another type of looping construct offered in programming is a conditional loop. Conditional loops continue looping until a certain condition is met. There are a few different methods of creating conditional loops in QB64. The first one we'll discuss is the DO...LOOP UNTIL statement. Type in the following code and then execute it.

The block of code contained in between the DO and LOOP UNTIL statements is looped until the LOOP UNTIL condition becomes true. Only when Count% contains the value of 24 does the loop exit. It's important to note that the code block with this form of DO...LOOP will always be executed at least one time since the conditional check isn't made until after the code block has been executed.

Here's a little sneak peek of things to come with a graphics program that uses a DO...LOOP construct that becomes true when the user presses the escape (ESC) key. Save the previous example as DoLoop.BAS before typing in the next example and executing it.

The code sample above uses commands that have not been encountered yet. Later lessons will eventually cover these commands but if you're curious beforehand you can view an alphabetical listing of QB64 commands here.

Save this program as Circle.BAS so we can revisit it in a later lesson.

The DO...LOOP statement has a couple of variations that can be used.

DO WHILE <condition is true>
.. <code block>

The code block in this variation may never get executed because the condition is checked before the code block is entered. The condition must be true before the code block is entered.

DO UNTIL <condition is true>
.. <code block>

Again, the code block may never get executed because of the condition being tested before it. The condition must be false before the code block is entered.

.. <code block>
LOOP WHILE <condition is true>

This variation continues to loop as long as the condition is true. The code block will get executed at least one time since the conditional check is done after the code block.

No DO...LOOP variation is considered better than another. The one you decide to use will depend on your program requirements at the time.

WHILE...WEND Looping

Another method of implementing a conditional loop is with the use of the WHILE...WEND statement. Type in the following program and execute it.

The code block in between a traditional DO...LOOP structure must be executed at least once before the loop's condition is checked. However, a WHILE...WEND structure allows the programmer to skip a code block completely because the condition is checked before the loop is entered. If the user enters a number below 101 the loop will execute at least once. This behavior is similar to the non-traditional DO WHILE...LOOP and DO UNTIL...LOOP constructs.

WHILE Count% < = 100 '     test condition before the loop is entered

As long as Count% is less than or equal to ( <= ) 100 the code block in the loop will be executed. If the user were to enter 110 the WHILE statement's condition would be false resulting in the code block never being executed.

The following relational operators can be used to check for conditions: = (equal to), < (less than), > (greater than), <> (not equal to), <= (less than or equal to), and >= (greater than or equal to).

Looping Speed Considerations

Looping constructs in QB64 do not have equal performance. FOR...NEXT loops are the slowest, followed by DO...LOOP UNTIL, WHILE...WEND, and then the variations that DO...LOOP offers.

FOR...NEXT loops are perfect for uses where speed is not going to affect game play, such as loading the game's assets (graphics, sounds, fonts, etc..) upon program start, or sorting the high score table at game end. However, during game play you're going to want your loops to be as fast as possible and that's where DO...LOOP and WHILE...WEND shine.

Type in the following program that highlights the speed differences between the various looping mechanisms. This code can also be found in your .\Tutorial\Lesson4 subdirectory as LoopSpeeds.BAS.

Loop speed comparisons on an Intel 6th Gen i7 CPU running at 4GHz

Your Turn

Create a program that combines the conversion utilities we created in lesson 2 into a menu driven program. Figures 1 and 2 below show how the output of your program should look.

Figure 1: Fahrenheit to Celsius

Figure 2: Inches to millimeters

- Invalid menu entries should be ignored.

- When the user enters the number 3 to end the program it should immediately terminate back to the operating system.

- The screen should be cleared before the menu is displayed.

- You'll need the following commands to complete this task: DIM, DO...LOOP, CLS, PRINT, IF...THEN, INPUT, SLEEP, and SYSTEM.

- Save the program as MenuLoop.BAS when finished.

Click here to see the solution.

Commands and Concepts Learned

New commands introduced in this lesson:

DO...LOOP (and variations)

New concepts introduced in this lesson:

frame rate
controlled loops
conditional loops