Lesson 3: Conditions and Branching

Going back to our first program, wouldn't it be cool that instead of the general Hello World, we could say Good Morning World!, Good Afternoon World!, or Good Evening World! depending on the time of day? For our next program we'll make the computer say Good Morning World! if the time is earlier than 12PM, Good Afternoon World! if the time is between 12PM and 6PM and Good Evening World! if the time is greater than 6PM. Type the following program into your IDE then execute it to see it in action.

( This code can be found at .\tutorial\Lesson3\HelloTime.bas )

'--------------------------------
'- Variable declaration section -
'--------------------------------

DIM Hour% ' the current hour of the day

'----------------------------
'- Main program begins here -
'----------------------------

Hour% = VAL(TIME$) '                get the current hour (military time 0-23)
IF Hour% < 12 THEN '                is current hour less than 12? (before noon)
   PRINT "Good Morning World!" '   yes, it must be morning
END IF
IF Hour% > 11 AND Hour% < 18 THEN ' is current hour 12 to 17? (noon to 5PM)
   PRINT "Good Afternoon World!" ' yes, it must be afternoon
END IF
IF Hour% > 17 THEN '                is current hour greater than 17? (after 5PM)
   PRINT "Good Evening World!" '   yes, it must be evening
END IF

Figure 1: Good evening

Before we analyze the program let's talk about the use of the < and > characters first. Just as you learned in math class the < character means less than and the > character means greater than. These characters are known as relational operators because they test the relationship between values.

The first line in the main program section gathers the current hour from the computer:

Hour% = VAL(TIME$) '                get the current hour (military time 0-23)

An integer variable named Hour% has been declared to hold the current hour of the day. TIME$ is a QB64  function that can retrieve the current time from the computer. As you may have guessed the time is returned as a string of characters because of the string identifier ( $ ) at the end of the command. TIME$ returns the current time in the format "HH:MM:SS" in 24 hour military time. So, for instance, 6PM is returned as "18:00:00".

VAL() is also a QB64 function. Think of a function as small ready to use program that performs a specific task. In the case of VAL() it returns the value of a string. In other words it converts any numeric characters contained in the string to an actual numeric value and returns that value either to be evaluated or placed within a variable such as our program did. VAL() will stop converting numbers when it reaches a non-numeric character within the string it is converting. Since the first two characters of TIME$ are the hour, VAL() will grab the first two characters, convert them to a numeric value, and then return that numeric value. In our program that numeric value is placed in Hour% because we told it to equal ( = ) the numeric result that VAL() returns. Here is the process broken down using the 6PM example:

TIME$ returns the time as a string of characters. Since TIME$ is contained within VAL()'s parenthesis it is handled first due to the order of operations.

Hour% = VAL("18:00:00")

The first two characters of the string are grabbed by VAL() because they are numeric characters. When VAL() sees the colon ( : ) it stops grabbing characters.

Hour% = VAL("18")

Now that VAL() contains only numeric characters in string format it converts those characters to an actual numeric value and returns it.

Hour% = 18

The next three lines of code is actually a statement wrapped inside of another statement.

IF Hour% < 12 THEN '               is current hour less than 12? (before noon)
   PRINT "Good Morning World!" '   yes, it must be morning
END IF

The IF...THEN...END IF is a statement construct used for true or false conditional testing, otherwise known as Boolean logic. The code contained in between the IF and THEN key words is known as a condition. This condition is evaluated to either having a true or false outcome. If the condition is evaluated to be true then anything that follows the THEN key word is executed. However, if the condition is evaluated to being false then anything following the THEN key word is ignored. We previously set Hour% to 18 so let's go ahead plug that value into the three lines of code to see what happens.

The number 18 is substituted for Hour%:

IF 18 < 12 THEN '                  is current hour less than 12? (before noon)
   PRINT "Good Morning World!" '   yes, it must be morning
END IF

Then the condition 18 < 12 is examined. Is 18 less than 12? No, so the condition evaluates to false:

IF FALSE THEN '                    is current hour less than 12? (before noon)
   PRINT "Good Morning World!" '   yes, it must be morning
END IF

Since the condition evaluated to false anything following the THEN statement will be ignored. Since 18 in military time is 6PM it can't possibly be morning so our IF...THEN statement prevented the code from printing that it is morning. Let's move onto the next three lines of code in the same manner.

The number 18 is once again substituted for each Hour%:

IF 18 > 11 AND 18 < 18 THEN '      is the current hour 12 to 17? (noon to 5PM)
   PRINT "Good Afternoon World!" ' yes, it must be afternoon
END IF

Here we have two conditions being evaluated, 18 > 11 and 18 < 18, separated by the use of the AND Boolean conditional operator. By using the AND conditional operator both conditions must evaluate to true to make the entire statement true. In other words this AND this must be true for the entire statement to be true. There will be more discussion on Boolean topics in a later lesson.

The first condition will evaluate to false since 18 is not greater than 11. The second condition will also evaluate to false sine 18 is not less than 18. If any condition on either side of the AND operator is false the entire statement becomes false. Once again, since 18 in military time is 6PM it can't possibly be afternoon so the IF...THEN statement prevented the code from printing that it's the afternoon.

IF FALSE AND FALSE THEN '          is the current hour 12 to 17? (noon to 5PM)
   PRINT "Good Afternoon World!" ' yes, it must be afternoon
END IF

Finally let's examine the last three lines of code again substituting the number 18 for Hour%:

IF 18 > 17 THEN '                  is current hour greater than 17? (after 5PM)
   PRINT "Good Evening World!" '   yes, it must be evening
END IF

The condition is examined and evaluated as true since 18 is in fact greater than 17.

IF TRUE THEN '                     is current hour greater than 17? (after 5PM)
   PRINT "Good Evening World!" '   yes, it must be evening
END IF

Since the condition this time evaluated to true the statement allows the code following THEN to be executed resulting in "Good Evening World!" printed to the screen.

The IF...THEN Statement

The IF...THEN statement construct can be used in a number of different ways to perform conditional testing. Let's start out with a simple program and then change it to see the different methods that can be used. Type the following code into your IDE and then execute it to see it in action.

'--------------------------------
'- Variable declaration section -
'--------------------------------

DIM Value% '    numeric value the user supplies

'----------------------------
'- Main program begins here -
'----------------------------

INPUT "Enter a number between 1 and 100 >", Value%
IF Value% < 1 THEN PRINT "That number is less than one!"
IF Value% > 100 THEN PRINT "That number is greater than one hundred!"
IF Value% > 0 AND Value% < 101 THEN PRINT "Thank you for following directions."

The user is asked to enter a number between 1 and 100 with the result getting stored into Value%. In all previous example code that contained IF...THEN statements there was an associated END IF line of code to show where the IF...THEN statements ends. However, you do not need the END IF statement if only one action is to be performed after the THEN statement as seen in the code above. For example, this line of code:

IF Value% < 1 THEN PRINT "That number is less than one!"

only has the PRINT statement as the single action to be performed if the condition evaluates to true.

While the program works as written there is another, more efficient method, to group the IF...THEN statements together using a modified version of the IF...THEN statement construct. Modify your code with the changes below.

'--------------------------------
'- Variable declaration section -
'--------------------------------

DIM Value% '    numeric value the user supplies

'----------------------------
'- Main program begins here -
'----------------------------

INPUT "Enter a number between 1 and 100 >", Value%
IF Value% < 1 THEN
   PRINT "That number is less than one!"
ELSEIF Value% > 100 THEN
   PRINT "That number is greater than one hundred!"
ELSE
   PRINT "Thank you for following directions."
END IF

The ELSEIF and ELSE statements are two optional statements you can use with IF...THEN statement constructs. ELSEIF allows for another condition to be tested if the previous condition evaluated to false.  The ELSE statement can be considered a "catch all" having statements after it executed only if every IF and ELSEIF above it had their conditions all evaluate to false. Let's say the user entered the numeric value 123 in the program above. The program flow would look like this:

The numeric value 123 is substituted for Value% in the IF line:

IF 123 < 1 THEN

This condition will obviously evaluate to false since 123 is not less than 1. Program flow will continue on to the ELSEIF statement:

ELSEIF 123 > 100 THEN

This condition will equate to true since 123 is greater than 100. Here, the action associated with the ELSEIF statement is acted upon resulting in "That number is greater than one hundred!" being printed to the screen. When a condition that evaluates to true has been encountered, and the associated action performed, the remaining IF...END IF statement structure is then ignored.  Let's look at the program flow again this time having the user enter the numeric value of 55.

The numeric value 55 is substituted for Value% in the IF line:

IF 55 < 1 THEN

This again is false so the program flow will continue on to the ELSEIF statement:

ELSEIF 55 > 100 THEN

Again, another false evaluation. Since there are no more ELSEIF statements to process program flow continues to the ELSE statement since every condition above has evaluated to false. Logically, if the numeric value the user entered was not less than one nor was it greater than one hundred then it must be a number in the range we are looking for. There was no need to perform a third test as we did in the first program example. This is much more efficient.

"Thank you for following directions."

Many actions can be taken within IF...THEN...END IF blocks of code. Modify the code one more time to see this principle in action.

( This code can be found at .\tutorial\Lesson3\1to100.bas )

'--------------------------------
'- Variable declaration section -
'--------------------------------

DIM Value% '    numeric value the user supplies

'----------------------------
'- Main program begins here -
'----------------------------

INPUT "Enter a number between 1 and 100 >", Value%
IF Value% < 1 THEN
   PRINT "That number is less than one!"
   PRINT "Perhaps you should read the directions."
ELSEIF Value% > 100 THEN
   PRINT "That number is greater than one hundred!"
   PRINT "Hello, McFly, directions are important!"
ELSE
   PRINT "Thank you for following directions."
END IF

The above code shows multiple actions within the IF and ELSEIF code blocks, in this case two PRINT statements. You can have as many actions within code blocks as you wish. You can even embed more IF statements inside if you like.

IF will also evaluate to true when testing against any non-zero value. The following IF statement will evaluate to false because the value contained in Test% is zero:

Test% = 0
IF Test% THEN PRINT "A non-zero value"

The PRINT statement will not get performed because a numeric value of zero is seen as false. changing the value of Test% to anything other than zero will result in the IF statement evaluating to true.

Test% = 99
IF Test% THEN PRINT "A non-zero value"

This time the PRINT statement will get performed.

Many times at the top of BASIC source code you'll see the following two lines:

CONST FALSE = 0
CONST TRUE = NOT FALSE

These are used as Boolean flags to set variables to true and false for IF testing purposes. The constant TRUE will equal the value of -1 (non-zero) because of the NOT Boolean operator statement reversing the value of the constant FALSE.

Test% = TRUE
IF Test% THEN
   PRINT "Evaluated to TRUE"
ELSE
   PRINT "Evaluated to FALSE"
END IF

The SELECT CASE...END SELECT Statement

Another form of conditional testing can be performed using the SELECT CASE...END SELECT statement construct that provides many powerful options for testing conditions. Let's take the first program from this lesson and rewrite it using SELECT CASE.

( This code can be found at .\tutorial\Lesson3\HelloCase.bas )

'--------------------------------
'- Variable declaration section -
'--------------------------------

DIM Hour% ' the current hour of the day

'----------------------------
'- Main program begins here -
'----------------------------

Hour% = VAL(TIME$) '                   get the current hour
SELECT CASE Hour% '                    what is the current hour?
   CASE IS < 12 '                      is it less than 12?
       PRINT "Good Morning World!" '   yes, it must be morning
   CASE 12 TO 17 '                     is it 12 to 17?
       PRINT "Good Afternoon World!" ' yes, it must be afternoon
   CASE IS > 17 '                      is it greater than 17?
       PRINT "Good Evening World!" '   yes, it must be evening
END SELECT

Conditional checks are performed using the CASE statement based off of a value to evaluate determined by the SELECT CASE line of code.

SELECT CASE Hour% '                    what is the current hour?

The variable Hour% is now used by the CASE statements to perform evaluations based on its value.

   CASE IS < 12 '                      is it less than 12?
       PRINT "Good Morning World!" '   yes, it must be morning
   CASE 12 TO 17 '                     is it 12 to 17?
       PRINT "Good Afternoon World!" ' yes, it must be afternoon
   CASE IS > 17 '                      is it greater than 17?
       PRINT "Good Evening World!" '   yes, it must be evening

A block of code is created between each CASE statement to carry out additional statements if the CASE statement evaluates to true. Each CASE statement acts like a separate IF statement but with a much cleaner syntax.

( This code can be found at .\tutorial\Lesson3\OddEvenCase.bas )

'--------------------------------
'- Variable declaration section -
'--------------------------------

DIM Number% ' numeric value provided by user

'----------------------------
'- Main program begins here -
'----------------------------

INPUT "Enter a number from 1 to 10 >", Number% '  get value from user
SELECT CASE Number% '                             what's the value?
   CASE IS < 1, IS > 10 '                         is it within range?
       PRINT '                                    no
       PRINT "You need to follow directions!" '   inform user to follow directions
   CASE 2, 4, 6, 8, 10 '                          was it an even number?
       PRINT '                                    yes
       PRINT "You entered an EVEN number." '      inform the user
   CASE ELSE '                                    if none of the above applies it must have been odd
       PRINT
       PRINT "You entered an ODD number." '       inform the user
END SELECT

The variable Number% is used as the evaluator for the CASE statements that follow.

SELECT CASE Number% '                             what's the value?

CASE statements allow multiple checks on the same line by separating them with commas (,).

CASE IS < 1, IS > 10 '                         is it within range?

If either condition is true the block of code that follows will be entered. The same is true for this line of code:

CASE 2, 4, 6, 8, 10 '                          was it an even number?

If Number% contains any of the values following the CASE statement then the condition becomes true and the block of code is entered. If you had to do this with an IF statement if would look like this:

IF Number% = 2 OR Number% = 4 OR Number% = 6 OR Number% = 8 OR Number% = 10 THEN

As you can see using CASE is a much cleaner and easier way to test for many conditions on the same line.

Just like IF statements the SELECT CASE construct has an ELSE clause to act as a "catch all" when none of the previous CASE statements evaluated to true.

CASE ELSE '                                    if none of the above applies it must have been odd

The following forms of CASE can be used with the SELECT CASE construct.

CASE Value

Here a single value is checked such as a numeric or string value. Examples would be CASE 10, CASE Number%, CASE "Mississippi", or CASE Pname$.

CASE Value1 TO Value2

A range of values can be checked such as CASE 1 TO 10, CASE -50 TO 100, or CASE n1% TO n2%.

CASE Value1, Value2, Value3, ...

Multiple values can be checked at the same time such as CASE 1, 3, 5 or CASE "A", "B", "C".

CASE IS > Value

Values can be checked against relational operators which include less than ( < ), greater than ( > ), equal to ( = ), less than or equal to  ( <= ), greater than or equal to ( >= ) and not equal to ( <> ).

By using commas you can mix and match these various forms of CASE on one line.

CASE 1, 5 TO 10, 15 '          check for 1, 5, 6, 7, 8, 9, 10, and 15
CASE IS < 1, IS > 10 '         check for a value outside the range of 1 to 10
CASE -10 TO -1, 1 TO 10 '      check for values within these ranges
CASE "A", "B", "C", "D", "F" ' check for these string values (grades)

SELECT CASE can be used as an alternative to multiple ELSEIF statements and it makes code cleaner and easier to read. The major difference between multiple ELSIF statements and SELECT CASE is that SELECT CASE can only test for one condition while multiple ELSEIF statements can check for many different conditions. Take this code for example:

IF Count% = 1 THEN
    'do this code
ELSEIF Count% = 2 THEN
    'do this code
ELSEIF Count% > 10 THEN
    'do this code
ELSE
    'do this code
END IF

The code above lends itself well to being converted to a SELECT CASE construct because only one variable, Count%, is being checked for different conditions. Here is the same code written with SELECT CASE.

SELECT CASE Count%
   CASE 1
        ' do this code
   CASE 2
        ' do this code
   CASE IS > 10
        ' do this code
   CASE ELSE
        ' do this code
END SELECT

However, the following IF...END IF construct would not be possible to do using a SELECT CASE statement.

IF Count% = 1 THEN
    ' do this code
ELSEIF Player% = 2 THEN
    ' do this code
ELSEIF Score% < 100 THEN
    ' do this code
ELSE
    ' do this code
END IF

The reason is that three different variables are being evaluated in the above example and there is no mechanism to allow SELECT CASE to test for more that one condition at a time. Again, the main reason to use SELECT CASE  is the versatility it offers when checking a condition and the readability it provides to the programmer. Many times you'll see programmers use SELECT CASE in the following configuration.

Frame% = Frame% + 1 '     increment frame counter
SELECT CASE Frame% '      which frame is game on?
   CASE 1: UpdateScores ' execute the score update subroutine
   CASE 2: AddEnemy '     execute the enemy adding subroutine
   CASE 3: ToggleEnemy '  execute the enemy appearance subroutine
   CASE 30: Frame% = 0 '  reset frame counter after 30 frames
END SELECT

Notice the use of a colon ( : ) after each CASE statement. Colons are a throwback from the early days of BASIC that allow multiple command statements to be placed on the same line of code. QB64 still supports the use of colons for compatibility reasons however they make code difficult to read and are rarely used. Sometimes though, as with the example above, they actually aid in enhancing code readability.

Branching With The GOTO Statement

The next portion of this lesson is a controversial subject in the programming world. There is a command in BASIC called GOTO that allows program execution to jump from one place to another within the source code. Most programmers avoid using this command because it is considered poor programming style to use it. Other programmers use it because they say it keeps with the spirit of the BASIC language. My personal opinion is that the GOTO command should be avoided because it can create what is known as spaghetti code, that is code that's hard to follow like a strand of spaghetti within a pile of thousands. However, the command does exist and you need to be aware of it in case you run across it within someone else's code.

So far all of the example programs you have worked with started at the top of the source code and proceeded toward the bottom on line at a time. The GOTO command allows you to jump backward or forward within the source code enabling reuse of the code. For example, type in the following program into your IDE and then execute it to see GOTO in action.

( This code can be found at .\tutorial\Lesson3\Goto.bas )

'--------------------------------
'- Variable declaration section -
'--------------------------------

DIM Count% ' used as a counter

'----------------------------
'- Main program begins here -
'----------------------------

Count% = 1 '                     set initial counter value

START: '                         a label GOTO can jump to

PRINT Count% '                   display current value of counter
count% = Count% + 1 '            increment the counter value
IF count% < 25 THEN GOTO START ' go back if counter less than 25

What the program has done is set up a loop until a certain condition is met. In order to use the GOTO command you need to create jump points called labels within your source code. Labels follow the same naming rules as variables and are followed by a single colon ( : ).

START: '                         a label GOTO can jump to

The label called START can now be used by a GOTO statement as a jump point. The program continues on by printing the value of the variable Count% and then incrementing, or adding 1, to the value of Count%. The last line of code is where the jump happens.

IF count% < 25 THEN GOTO START ' go back if counter less than 25

If the value in Count% is less than 25 then GOTO directs program flow back to the label named START and the process starts over again. This looks harmless enough in a simple program as above, but let's up the ante a bit. Type in the following program and execute it.

( This code can be found at .\tutorial\Lesson3\NoNoGoto.bas )

'--------------------------------
'- Variable declaration section -
'--------------------------------

DIM Count% '     used as a counter
DIM Remainder% ' the remainder of modulus division

'----------------------------
'- Main program begins here -
'----------------------------

Count% = 1 '                     set initial counter value
START: '                         back to the beginning
PRINT Count%; '                  display current value of counter
GOTO TESTREMAINDER '             is number odd or even?
EVEN: '                          jump here if even
PRINT "EVEN" '                   display EVEN after number
GOTO CONTINUE '                  continue with program
ODD: '                           jump here if odd
PRINT "ODD" '                    display ODD after number
GOTO CONTINUE '                  continue with program
TESTREMAINDER: '                 what was result of modular division?
IF Remainder% = 0 THEN '         was there a remainder?
   GOTO EVEN '                   no, must be even, go there
ELSE '                           yes, there was a remainder
   GOTO ODD '                    must be odd, go there
END IF
CONTINUE: '                      continue program here
Count% = Count% + 1 '            increment counter
Remainder% = Count% MOD 2 '      get the remainder of modulus division
IF Count% < 25 THEN GOTO START ' loop if counter less than 25

Granted, I've taken the use of GOTO to a bit of an extreme in this example, however, even this little program is difficult to follow at best. The use of GOTO may seem like a good idea at first but before you know it your code becomes an absolute mess to decipher. In later lessons you will learn superior alternatives to using GOTOs for looping.

Random Outcomes

There are going to many circumstances where randomness will be desired and needed. Let's face it, a game that is predictable becomes boring rather quickly. Take Pac-Man for instance. Soon after the game was released in the arcades in the early 1980s players found "patterns" to follow and achieved astronomical levels and scores. These patterns worked time and time again and it didn't matter which Pac-Man machine you were playing on. The reason for this was that the ghosts were governed by movement algorithms that would produce the same values with each given level. There was no randomness included in the algorithms. The designers of Pac-Man did a fantastic job on the movement algorithms but random number generating statements were not at their disposal. Generating random numbers takes more horsepower than what was available back then on those primitive CPUs.

Fortunately today's CPUs have no problem with generating random numbers. QB64 will happily generate millions of random numbers for you in the blink of an eye.

The RND Statement

The RND statement is used to generate a random number from 0 to .9999999. In its simplest form there are no parameters needed:

PRINT RND ' print a randon number from 0 to .9999999

or assign the random number to a variable:

RandomNumber! = RND ' create and store a random number from 0 to .9999999

There's a problem with random number generators in ALL computers however, they are not truly random. Start a new program in your IDE and type the following lines of code in:

PRINT RND
PRINT RND

Go ahead and run the code. Write down the two values that were printed to the screen. Now, run the code again and compare the numbers on the screen with what you wrote down. Look familiar? Random number generators in computers are known as pseudorandom number generators. The numbers they produce appear to be random in nature but in actuality are not. This is a problem computer scientists have been working on for years; how do you generate truly random numbers? There are ideas but for now this problem still exists.

But all is not lost as there is a work-around to this problem that will keep the same random numbers from appearing over and over again.

The RANDOMIZE Statement

The RANDOMIZE statement is used to "seed" the computer's random number generator with a start value to generate different random number sequences. RANDOMIZE needs a seed number to pass along to the random number generator. If you were to use the same seed number over and over the problem of the same random numbers being generated would still exist. We need a number that is constantly changing as the computer is running:

RANDOMIZE TIMER ' seed the random number generator

QB64 has a function called TIMER that records the number of seconds that have passed in the day with millisecond accuracy. That's 86,399 seconds that are kept track of each day. Each day at midnight the TIMER is reset back to 0. Since TIMER is never the same value throughout the day it makes a perfect seed number. Go ahead and try it. Change the code you currently have in your IDE to this:

RANDOMIZE TIMER
PRINT RND
PRINT RND

Just like last time run the code a few times and see if you get the same random numbers. Ah ha! Problem solved ... well, mostly.

It's possible, but highly improbable, that your program is run at the exact same millisecond on two different days which once again will yield the exact same sequence of random numbers. If this is a concern then there are other values that are constantly changing in QB64 such as the date (DATE$) and time (TIME$). Getting creative by perhaps adding the day of the month and the current hour to the TIMER value will add even more "randomness" to your seed number.

Ok, you've probably thought by now that while random numbers are great what good are they if you can't generate random numbers, say, from 1 to 100? You can!

Random Number Ranges

By introducing a little math you can generate random numbers in any range you like. By simply multiplying the random number you can increase its value:

RandomNumber! = RND * 100 '      generate a random number from  0 to  99.99999
RandomNumber! = RND * 100 + 50 ' generate a random number from 50 to 149.9999

In a later lesson you'll be introduced to the INT statement. The INT statement is used to extract just the integer portion of a number:

RandomNumber% = INT(RND * 100) '      generate a random number from  0 to  99
RandomNumber% = INT(RND * 100) + 1 '  generate a random number from  1 to  100
RandomNumber% = INT(RND * 100) + 50 ' generate a random number from 50 to  150
RandomNumber% = -INT(RND * 100) - 1 ' generate a random number from -1 to -100

Let's see how random numbers can be useful in decision making and code branching. The following program throws a pair of dice and displays the results. Type in the following program.

( This code can be found at .\tutorial\Lesson3\DiceThrow.bas )

'--------------------------------
'- Variable declaration section -
'--------------------------------

OPTION _EXPLICIT ' force variables to be declared

DIM Die1% '        die number 1's value
DIM Die2% '        die number 2's value
DIM Count% '       die counter
DIM DieValue% '    value of the current die
DIM Enter$ '       wait for enter key to be pressed

'----------------------------
'- Main program begins here -
'----------------------------

PRINT '                                          print header and instructions
PRINT " Dice Throwing Game"
PRINT " ------------------"
PRINT
PRINT
" Press the ENTER key to throw the dice.";
INPUT Enter$ '                                   wait for ENTER to be pressed
PRINT
RANDOMIZE TIMER '                                seed the random number generator
Die1% = INT(RND * 6) + 1 '                       create random number from 1 to 6
Die2% = INT(RND * 6) + 1 '                       create random number from 1 to 6
Count% = 0 '                                     reset die counter
LOOPBACK: '                                      jump back here to draw both dice
Count% = Count% + 1 '                            increment die counter
IF Count% = 1 THEN '                             counter on die 1?
    DieValue% = Die1% '                          yes, get the value of die 1
ELSE '                                           no, must be 2 then
    DieValue% = Die2% '                          get the value of die 2
END IF
PRINT " +-------+" '                             print top of die
SELECT CASE DieValue% '                          what is the current die roll?
   CASE 1 '                                      a one was rolled
       PRINT " |       |" '                      print body of die for a 1
       PRINT " |   *   |"
       PRINT " |       |"
   CASE 2 '                                      a two was rolled
       PRINT " | *     |" '                      print body of die for a 2
       PRINT " |       |"
       PRINT " |     * |"
   CASE 3 '                                      a three was rolled
       PRINT " | *     |" '                      print body of die for a 3
       PRINT " |   *   |"
       PRINT " |     * |"
   CASE 4 '                                      a four was rolled
       PRINT " | *   * |" '                      print body of die for a 4
       PRINT " |       |"
       PRINT " | *   * |"
   CASE 5 '                                      a five was rolled
       PRINT " | *   * |" '                      print body of die for a 5
       PRINT " |   *   |"
       PRINT " | *   * |"
   CASE 6 '                                      a six was rolled
       PRINT " | *   * |" '                      print body of die for a 6
       PRINT " | *   * |"
       PRINT " | *   * |"
END SELECT
PRINT " +-------+" '                             print bottom of die
PRINT
IF Count% = 1 THEN GOTO LOOPBACK '               jump back to print die 2
PRINT " You rolled a total of"; Die1% + Die2% '  print total dice roll

Figure 2: How about a game of dice?

This program uses QB64's random number generator to create a pair of dice values in lines 25 and 26:

Die1% = INT(RND * 6) + 1 '                       create random number from 1 to 6
Die2% = INT(RND * 6) + 1 '                       create random number from 1 to 6

The random numbers generated by RND in these lines is multiplied by 6, yielding a value of 0 to 5.999999. The INT statement extracts only the integer portion of the number yielding a value of 0 to 5. One is then added so the final outcome is a value of 1 to 6. To ensure the dice values are random at each program execution the RANDOMIZE TIMER statement has been included in line 24.

To print each die to the screen a counter, Count%, is used to keep track of which die is currently being evaluated. Lines 30 through 34 then decide based on Count% which die value should be placed into the variable DieValue%.

Line 36 then makes a decision based on DieValue% as to which die body should be printed. Once the die body has been printed line 64 makes the decision to go back to the line label LOOPBACK: contained in line 28. If Count% is equal to 1 then only the first die has been printed and the second die needs printing. If Count% is anything other than 1 then the program continues to line 65 printing the total of the dice thrown.

Your Turn

Create a Guess The Number game that exhibits the following features:

- The program should display the game's rules to the player.

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

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

- The program should tell the player if the number guessed is too high or low.

- The program will use GOTO to create a loop.

- The program should end once the user correctly guesses the number.

- Don't forget to document your code using remarks.

The commands you will need to use in order to create this game are PRINT, INPUT, GOTO, IF...THEN , RND, RANDOMIZE, and DIM. Save the program as Guess.BAS to your hard drive. Figure 3 below shows a screen shot of how your Guess The Number game should play out.

Figure 3: An example game of Guess the Number

Commands and Concepts Learned