Beginning Programming 4 - Section Two

by Brad Moore

Just a bit of Chance

Now for Something Different...

Switching gears a little bit, lets do a little exercise writing a simple game. It will be a thin version of the casino game Craps. I am hoping that the introduction of a game of chance does not cause any undue consternation in the readership - I certainly am not condoning gambling, and in fact this little game does not include any betting, merely the random qualities and basic rules for play that result in either winning or losing.

Here are the basic rules we will be using: Two dice are used. Initial roll of the dice is to establish the "point" which you will be trying to roll again. Rolling a 7 or 11 with your first roll is an automatic win. Rolling a 2, 3 or 12 with your initial roll is an automatic loss. An initial roll of 4, 5, 6, 8, 9 or 10 establishes the "point".

Once a point is established the player must roll the dice again (repeatedly until they win or lose). Rolling the "point" again is a win. Rolling a 7 is a loss. Our game will not have any component of betting. You are welcome to expand the game if you choose.

Because this is a simple version of the game Craps, I decided to call it "Crumb". Based on the rules above we should be able to map out a simple bit of pseudo code. I would suggest that you try your hand at creating this before moving on.

This is my first cut at some simple pseudo code:

1) Ask the user of they need instructions and show them if required

2) Roll 2 dice by finding two random values 1 to 6

3) Total the value of the two dice

4) Evaluate the result:

4a) If the dice total equals 7 or 11 you win - goto 8

4b) If the dice total equals 2, 3 or 12 you lose - goto 8

4c) This is your point value

5) Roll 2 dice by finding two random values 1 to 6

6) Total the value of the two dice

7) Evaluate the result:

7a) If the dice total equals 7 you lose - goto 8

7b) If the dice equals your point value you win - goto 8

7c) goto 5 and roll dice again

8) Ask the player if they want to play again

9) if the respond with "yes" goto 2

10) End

The outline presents a fairly simple program. I created a program based on the outline. It runs in the basic Liberty Basic consol and uses simple input and print statements for interaction with the user.

Some New Concepts -

The program introduces a couple new concepts along the way. These are easy tricks that you can use to make your program more robust when dealing with user input. I want to explain these before we see the program. You will find these twice in the program. Here is a sample snippet:

'See if the user needs instructions
input "Do you require instructions (y or n)";a$

'shift the user's answer to upper case
a$ = upper$(a$)

'use the instr() function to search the string for a 'Y'
if instr(a$,"Y") > 0 then

Here is what is going on. The input statement is basic enough. We have covered it a few times. It simply presents the user with a prompt and then collects a string value. Now the problem is that the user is not forced to enter a 'y' or an 'n' like we request. Best case they might enter a capitalized 'Y' or the word 'yes' - how do we react to this to be sure the user meant what we have evaluated when examining the result of the input statement?

Well we can first insure we (the program and the user) are operating using the same case. I always do this by either forcing the user's input to upper case letters or to lower case letters. Do this with the string function UPPER$() - for upper case text, and LOWER$() - for lower case text. These are simple functions that simply force the entire string into the desired case. This is good, because now I only need to test one case.

I actually do the testing using the INSTR() function. This is a new function, and it too is a string function. It searches through a given string looking for any occurrence of a specific search string. I know this seems like a complex concept to grasp. Consider this analogy: You have been putting together a puzzle. You have a small pile of puzzle pieces and you realize the one hole matches a puzzle piece shape and color pattern that you have seen recently in the pile. With the image of the piece you are seeking you begin looking through the pile, comparing each piece with the empty hole. Soon you find a match. This is what the INSTR() function does. It has a given source string and a second search string. It starts at the beginning of the source string and compares it to the search string. If it does not match it shifts right a character and compares again until it finds a match. If it does find a match it returns the character position within the source string where that match begins. If it does not find a match, then it returns a zero. Here is an example:

The source string:

A$ = "The brown dog is too slow"

The search string (the one we want to locate in the source string):

"br"

The function will search from the first character going right looking for the search string. In the steps below the potion being compared with the search string will be enclosed in brackets "[ ]".

1. "[Th]e brown dog is too slow" : Does "Th" equal "br"? - NO!
2. "T[he] brown dog is too slow" : Does "he" equal "br"? - NO!
3. "Th[e ]brown dog is too slow" : Does "e " equal "br"? - NO!
4. "The[ b]rown dog is too slow" : Does " b" equal "br"? - NO!
5. "The [br]own dog is too slow" : Does "br" equal "br"? - YES it does!

So we found a match on the 5th character, so the value 5 is returned by the function.

Do you see the power in the function in relation to the code sample? We do not have to search for multiple strings, like "y" and "Y" and "yes" and "Yes" to cover all the different permeations of the possible answer YES that the user could use. Nearly any positive response will begin with a "y". All we need to do is see the "y" and we presume they have responded affirmatively. And we know that if the INSTR() function returns a value greater than zero. A zero would indicate a negative response (or even the lack of a response) - a condition that would cause us to skip showing the user the instructions.

Another thing to notice in the program is that we are throwing two dice. The sum of the two dice will be a number between 2 and 12. We could have simply had the computer spit out a random number between 2 and 12, but the result would not be the same as if you had actually thrown two dice and summed the result. The reason is simple. When using two dice there are is more than one way to arrive at some numbers, such as 6 which can be made by combining 2 with 4, 1 with 5 and 3 with 3. eight can be made by combining 6 with 2, 5 with 3 and 4 with 4. This causes these "middle" numbers to appear more regularly than two or three or eleven or twelve. This is an important consideration when trying to create authentic games.

The final item I wanted to mention about the game I have written is that I relies heavily on GOTO in the program. It is not my favorite way of coding. I would actually have used different flow control in some cases, but we have not discussed any of the more advanced forms of flow control. This is not to say that GOTO is bad (many people think it is), but rather to say that there are times when a different type of flow control might be clearer, more easy to understand.

Having covered a few of these items, I am also hoping that you will take a stab at your own creation to create a game based on the pseudo code above, and the game rules outlined. I have provided many hints regarding tricks and techniques.

Crumb: The Program

What follows is my version of the program that was built from the pseudo code. I have not annotated it as other programs that we have worked through. There is sufficient comments to understand my intent, and program is fairly simple. Please enjoy.

'Crumb - a basic game of chance based on Craps
'by Brad Moore
'copyright 2003.  - placed in the public domain
'
'written for Liberty Basic version 3.x

'See if the user needs instructions
input "Do you require instructions (y or n)";a$

'shift the user's answer to upper case
a$ = upper$(a$)

'use the instr() function to search the string for a 'Y'
if instr(a$,"Y") > 0 then
   instruction$ = "This is a game of chance played with two dice.  " + _
   "The player is called the shooter.  When the shooter rolls a " + _ 
   "7 or 11 on the first throw it is called a 'natural' and you win.  " + _
   "On the other hand, if 2, 3 or 12 is rolled, the shooter is said " + _
   "to have 'rolled craps' and they lose.  Any other number 4, 5, 6, " + _ 
   "8, 9, or 10 becomes the shooters 'point'. The shooter must now roll " + _
   "the dice until they roll their 'point'.  If they roll their point " + _
   "number before they roll a 7 they win.  The shooter loses if a 7 " + _
   " is rolled before they make your 'point'." 
   notice instruction$
end if

'Make a place to loop back to...
[begin]

'Now start the play by having the user press enter...
input "Press the enter key to roll the dice...";a$

'Now we need to get two separate random numbers between 1 and 6
dice1 = int(rnd(1) * 6) + 1
dice2 = int(rnd(1) * 6) + 1
diceTtl = dice1 + dice2

Print "You have rolled a ";diceTtl;" (dice1 = ";dice1;", dice2 = ";dice2;")"

'Now determine the outcome
if diceTtl = 7 or diceTtl = 11 then
   Print "WAY TO GO! You have won!"
   goto [PlayAgain]
end if

if diceTtl = 2 or diceTtl = 3 or diceTtl = 12 then
   Print "You crapped out - you lose!"
   goto [PlayAgain]
end if

'Some nice formatting
print ""
print "--------------------------------------------------------"

'We now know the new POINT value
point = diceTtl
print "Your point you are trying to make is : ";point

'Now we will roll until we crap out or win - I will use a goto loop
'here because we have not covered more complex flow control
[rollLoop]
'Now press enter to roll again...
input "Press the enter key to roll the dice...";a$

'Now we need to get two separate random numbers between 1 and 6
dice1 = int(rnd(1) * 6) + 1
dice2 = int(rnd(1) * 6) + 1
diceTtl = dice1 + dice2

Print "You have rolled a ";diceTtl;" (dice1 = ";dice1;", dice2 = ";dice2;")"

'see if we win or lose
if diceTtl = 7 then
   Print "You crapped out - you lose!"
   goto [PlayAgain]
end if

if diceTtl = point then
   Print "You have made your point - You WIN!"
   goto [PlayAgain]
end if

'more nice formatting
print ""
print "-------------------------------------------------"

'we did not win or lose - go to the rollLoop label and do it again...
goto [rollLoop]

'The game is over - see if the user wants to play again...
[PlayAgain]
'more nice formatting
print ""
print "-------------------------------------------------"
Input "The game is over.  Do you want to play again (y or n)";a$

'shift the user's answer to upper case
a$ = upper$(a$)

'use the instr() function to search the string for a 'Y'
if instr(a$,"Y") > 0 then 
   'more nice formatting
   print ""
   print "-------------------------------------------------"
   goto [begin]
end if

print "Thanks so much for playing - have a nice day..."
end

As I said, the game is very simple. Perhaps you can think of some ways to enhance the game, for instance tracking wins versus losses. I would encourage you to play around with the program as this is the best way to learn. We will be revisiting this program in a coming beginners edition when we convert it to a real windows based game program.