Task 7  Task 7: Looping  Task 7


Most, if not all, computer programs today 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, the user, or both. In the gaming world the faster a game program can loop the better. Gamers like this because it enables their games to have faster FPS (Frames Per Second) otherwise known as the game's frame rate.

-- FOR...NEXT Looping --

Remember this program we created in Task 6 and saved as GOTO.bas? It counts from 1 to 24 while displaying the count on the screen.

'--------------------------------
'- Variable Declaration Section -
'--------------------------------

DIM Count% '                     a generic counter

'----------------------------
'- Main Program Begins Here -
'----------------------------

Count% = 1 '                     set initial value

START: '                         GOTO label

PRINT Count% '                   display current value of variable
Count% = Count% + 1 '            increase the value of the variable by 1
IF Count% < 25 THEN GOTO START ' go back if variable is less than 25

Well, as mentioned before, there is a much better and easier way to create a loop that does the same thing.

'--------------------------------
'- Variable Declaration Section -
'--------------------------------

DIM Count% ' a generic counter

'----------------------------
'- Main Program Begins Here -
'----------------------------

FOR Count% = 1 TO 24 ' increment Count% from 1 to 24 in steps of 1
    PRINT Count% '     print current value of Count%
NEXT Count% '          keep looping until Count% = 24

The FOR...NEXT statement was built for the sole purpose of controlled loops. A controlled loop is one where you explicitly know the starting and ending values of the loop and the loop continues until the ending value is reached. FOR...NEXT statements can count forward or backward in any increment you like. The default behavior of 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

In the above line of code 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 count to take place. The first time the loop runs Count% will contain the value of 1, the second time the loop runs Count% will contain the value of 2 and so on. This continues to happen until Count% finally reaches the end value of 24. This line controls when the loop ends:

NEXT Count%

Only when the NEXT statement sees that Count% equals the ending value of the loop will it exit the loop, otherwise it returns back to the FOR statement so the next loop can occur. All code contained in between the FOR and NEXT statements is executed over and over again until the FOR...NEXT loop ends. Notice how the IDE has once again indented the code within the FOR and NEXT statements for you, indicating that a block of code exists between the two. In our case a PRINT statement is simply printing the current value of Count% to the screen over and over, displaying the value of Count% for each loop.

-- Stepping It Up --

The STEP statment may be used in conjuntion with the FOR...NEXT statement to change the default count behavior. Save the previous example program as FORNEXT.bas before typing in the next program and executing it.

'--------------------------------
'- Variable Declaration Section -
'--------------------------------

DIM Cstep% '    FOR...NEXT step value
DIM Count% '    FOR...NEXT count value
DIM NextStep$ ' user input for next step

'----------------------------
'- Main Program Begins Here -
'----------------------------

FOR Cstep% = 1 TO 4
    CLS
    PRINT "Counting from 0 to 12 by steps of"; Cstep%
    PRINT
    FOR Count% = 0 TO 12 STEP Cstep%
        PRINT Count%
    NEXT Count%
    PRINT
    IF Cstep% < 4 THEN
        INPUT "Press ENTER for the next STEP value", NextStep$
    END IF
NEXT Cstep%

Before we analyze the above program there is a new command to explain. The CLS statement clears the current text or graphics screen of all contents.

The program above is using two FOR...NEXT loops, one inside the other, to create a nested loop. The outer loop, Cstep%, counts from one to four while the inner loop, Count%, counts from zero to twelve with a STEP value based on the current value of Cstep%. It just so happens that counting from zero to twelve by any of the Cstep% values allows the loop to end on the number twelve each time, because twelve is evenly divisible  by the numbers one through four. But, what happens if we use a STEP value that mathematically can't reach the ending number? If the next STEP value equals, or is greather than, the ending loop value, then the loop is considered complete. Make the following modifications to the above program 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%

And then execute the program again.

As you can now see STEP will only reach the value of twelve by counting in steps of one. Counting in steps of two, three or four can't mathmatically reach number the twelve. This is important to remember when writing your programs. Save this program example as STEPUP.bas before continuing on.

-- Stepping It Down --

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

'--------------------------------
'- Variable Declaration Section -
'--------------------------------

DIM CountDown% ' the count down timer value
DIM LiftOff% '   lift off sequence counter

'----------------------------
'- Main Program Begins Here -
'----------------------------

PRINT "Rocket launch in T minus ..."
FOR CountDown% = 10 TO 0 STEP -1
    SLEEP 1
    PRINT
    PRINT CountDown%; "..."
    IF CountDown% = 3 THEN
        PRINT
        PRINT "We have engine ignition ..."
    END IF
NEXT CountDown%
PRINT
PRINT "And liftoff ... !"
SLEEP 1
PRINT
_DELAY .1
PRINT " /\"
_DELAY .1
PRINT " ||"
_DELAY .1
PRINT " ||"
_DELAY .1
PRINT " ||"
_DELAY .1
PRINT "/||\"
_DELAY .1
PRINT "~||~"
_DELAY .1
PRINT " ^^"
_DELAY .1
PRINT
FOR LiftOff% = 1 TO 25
    _DELAY .1
    PRINT
NEXT LiftOff%
SYSTEM

Yes, I know, it's a pretty crude representation of a rocket launch, but we'll come back to this in a later task and spruce it up a bit. There are three new commands in the program above, SLEEP, _DELAY and SYSTEM.

SLEEP puts the computer into a continuous loop for a given number of second(s), which in effect stops it from execution for that amount of time. If you do not specify the number of seconds to SLEEP, the program will stop execution indefinitely until the user presses a key.

_DELAY (yes, the underscore is needed, more on that in a later task) 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 make 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  second.

We learned previously that the END statement forces a program to end execution, or to terminate. But, this leaves the program's screen behind infoming the user to "Press any key to continue ..." to close the window. SYSTEM on the other hand will terminate the program and close its window all at once, returning control back to the operating system without the user having to interact in any way. Go ahead and save this example code as STEPDOWN.bas before continuing.

-- DO...LOOP UNTIL Looping --

The next type of loop you can take advantage of with QB64 is a conditional loop, that is, a loop that continues until a certain condition is met. There are few different methods of implementing 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.

'--------------------------------
'- Variable Declaration Section -
'--------------------------------

DIM Count% ' a generic counter

'----------------------------
'- Main Program Begins Here -
'----------------------------

DO '                      start of loop
    Count% = Count% + 1 ' increment counter by 1
    PRINT Count% '        display value of variable
LOOP UNTIL Count% = 24 '  keep looping until statement is true

With this program the block of code contained in between the DO and LOOP UNTIL statements is looped until the LOOP UNTIL statement becomes true. Only when Count% contains the value of 24 does the loop exit. It's important to note that the code contained in the block between the DO and LOOP UNTIL statements will always be executed at least one time, because the condition is not tested for the first time until the bottom of the loop. Here's a little sneak peek of things to come with a graphics program that uses a DO...LOOP UNTIL statement 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.

'--------------------------------
'- Variable Declaration Section -
'--------------------------------

DIM x% ' x location of circle
DIM y% ' y location of circle
DIM r% ' radius of circle

'----------------------------
'- Main Program Begins Here -
'----------------------------

SCREEN _NEWIMAGE(640, 480, 32) '             640x480 graphics screen
x% = 320 '                                   x center of screen
y% = 240 '                                   y center of screen
r% = 20 '                                    set radius of circle
DO '                                         main loop begins here
    CLS '                                    clear the screen
    PRINT "Arrow keys to move the circle." ' display directions to user
    PRINT "ESC key to exit program."
    CIRCLE (x%, y%), r%, _RGB32(255, 0, 0) ' draw a red circle
    PAINT (x%, y%), _RGB32(255, 0, 0) '      paint inside the circle red
    IF _KEYDOWN(20480) THEN y% = y% + 1 '    was down arrow key pressed?
    IF _KEYDOWN(18432) THEN y% = y% - 1 '    was up arrow key pressed?
    IF _KEYDOWN(19200) THEN x% = x% - 1 '    was left arrow key pressed?
    IF _KEYDOWN(19712) THEN x% = x% + 1 '    was right arrow key pressed?
    _DISPLAY '                               update screen with changes
    _LIMIT 100 '                             loop will run at 100 FPS
LOOP UNTIL _KEYDOWN(27) '                    stop loop when ESC key pressed
SYSTEM '                                     return control to OS

Note: As you can see in the example code above there are a number of commands that have not been discussed yet. Instead of explaining each new command in every piece of example code encountered it will be left up to you to investigate the new commands that are not covered immediatly. Further tasks will eventually get to the commands not discussed. An alphabetical listing of QB64 commands can be found here (bookmark or add it to your favorites in your browser for later reference).

Save this program as CIRCLE.bas so we can revisit it in a later task.

-- WHILE...WEND Looping --

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

'--------------------------------
'- Variable Declaration Section -
'--------------------------------

DIM Count% '  a generic counter

'----------------------------
'- Main Program Begins Here -
'----------------------------

PRINT "This program will count to 100 from the number you supply."
PRINT
INPUT "Enter the number to start counting from > ", Count%
WHILE Count% <= 100
    PRINT Count%
    Count% = Count% + 1
WEND

As mentioned before, the code block in between the DO and LOOP UNTIL statements must be executed at least once before the loop's condition is checked. However, a WHILE...WEND statement 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.

WHILE Count% <= 100

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

Note: 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 Variations --

The DO...LOOP UNTIL statement has a couple of variations that can be used. They are:

DO WHILE <condition>
..
..
LOOP

This variation checks for a true condition before the code block is entered. This may result in the loop never actually being used.

DO UNTIL <condition>
..
..
LOOP

This variation checks for a false condition before the code block is entered. This may result in the loop never actually being used.

DO
..
..
LOOP WHILE <condition>

This variation checks if the condition is true before running the loop again. This assures that the loop is executed at least one time.

DO
..
..
LOOP UNTIL <condition>

Of course, this is the variation we discussed in detail and checks if the condition is false before running the loop again. This assures that the loop is executed at least one time.

Because the DO...LOOP UNTIL statement has so many variations some programmers frown upon the use of the WHILE...WEND statement, pointing to the superior options that DO...LOOP UNTIL offers instead. As a programmer you'll develop your own coding style and the use of DO...LOOP UNTIL versus WHILE...WEND is completely up to you. Use whatever construct you feel most comfortable with. Save the example program you have in your IDE as X_TO_100.bas before moving on.

-- Your Turn --

In Task 6 you created a Guess The Number game where the user guessed the number the computer was thinking of. However, after playing the game the program would exit. You need to modify this program to exhibit the following features:

- The program should display the game rules to the user.

- The number should be in the range of 1 to 100.

- The program keeps track of how many guesses the user made until guessing the right number.

- The program should tell the user if the number they guessed was too high or too low.

- When the user guesses the correct number the program should ask the user if he/she wishes to play again.

- If the user wishes to play again the program should start over with a new number to guess and clears the screen of the last game.

- Do not use the GOTO command.

- The following line of code will generate a random number between 1 and 100:

Rnumber% = INT(RND(1) * 100) + 1

(Don't forget to declare Rnumber% in the declaration section of your code. More will come in a later task explaining the functions INT() and RND().)

Guess 2
Figure 1 - Guess The Number version 2.0

When you are finished save the game as GUESS2.bas.


-- COMMAND REFERENCE --


Commands learned in previous tasks:

PRINT
INPUT
DIM
REM or '
CONST
TIME$
VAL()
IF...THEN
AND
END
GOTO
SELECT CASE...END SELECT
CASE
TO
IS
CASE ELSE
colon ( : )

New commands introduced in this task:

FOR...NEXT
STEP
CLS
SLEEP
_DELAY
SYSTEM
DO...LOOP UNTIL (and variations)
WHILE...WEND

Concepts learned in previous tasks:

execute
statement
expression
literal string
syntax error
variables
type declarations
literal strings
concatenation
integers
long integers
single precision
double precision
strings
null strings
reserved words
operators ( +, -, *, / )
declare
constant
relational operators
functions
nesting
order of operations
Boolean
conditions
indenting
loops
labels

New concepts introduced in this task:

frame rate
controlled loops
conditional loops