Jackpot
Up
Before attempting this project, please do the very easy 'Random Number' Project. 

In this 'Jackpot' project we will make a program resembling a slot machine - it will generate random numbers and if any of the numbers are sevens then we will win a 'prize' (a nice message!"). In this project you will learn about:

bulletcontrol arrays
bulletvariable arrays
bulletFor...Next loops
bulletthe relationship between numbers and the conditions 'true' and 'false'
bulletrandom numbers (extra practice)

If you currently have a project open in Visual Basic then remove it (File/Remove Project) then make a new project (File/New Project). Make sure you choose a Standard EXE project. Save the project immediately with File/Save Project (not Ctrl-S, for that only saves the form file). Create a new folder called JackPot to hold the various parts of the project, then save the form file and the project file, both with the same name as the folder. Don't forget to save your work every 10 minutes or so (you CAN use Ctrl-S for this).

Add a label called lblNum and a command button called cmdSpin to the form and set properties until the form looks like this. I chose Arial size 100 for the label. Choose your own colours (you will need to set the command button's style property to 'graphical' before its backcolor setting has any effect. Set the caption of the form to be "Jackpot! by (YOUR NAME HERE)".

Let's make the spin button put a random integer between 0 and 9 into the label. Having studied the 'Random Number' project, you will know what code to give the button:

Private Sub cmdSpin_Click()
lblNum.Caption = int(10 * rnd())
End Sub

Let's not forget that every program that uses the rnd() function should have Randomize in the Form_Load procedure, so double-click the form and add the code:

Private Sub Form_Load()
Randomize
End Sub

Having got that working, let's think about how to put random digits into three labels at the same time. Instead of making the new controls in the usual way, make them this time by copying and pasting the existing lblNum label. When you do this, VB will ask you whether you want to make a 'control array'. Normally we would answer 'no' to this question but this time we will answer 'yes' so that we can learn about control arrays and because it may make our code a little neater.

Examining the properties of the three labels, you should notice that they all have the same name (lblNum). How can the code distinguish between them? Look closely and you will see that each label has an index property that is not blank as it was for all controls in previous projects. The index values are 0, 1 and 2, so the left label is referred to as lblNum(0), the middle one as lblNum(1) and so on. Computers like to start counting from zero rather than from one, and you must be aware of this when programming in VB.

The following code would work fine for putting random numbers in each label:

Private Sub cmdSpin_Click()
lblNum(0).Caption = Int(10 * Rnd())
lblNum(1).Caption = Int(10 * Rnd())
lblNum(2).Caption = Int(10 * Rnd())
End Sub

You can try the above code if you like, but I am going to suggest that we use the following code instead, because it is shorter and neater and will teach us more about VB:

Private Sub cmdSpin_Click()
For n = 0 To 2
    lblNum(n).Caption = Int(10 * Rnd())
Next
End Sub

This is the first time we have used a For...Next loop in our code. How does it work? It begins by running the code inside the loop a first time, using the value of 0 for the counter variable 'n'. When the loop runs the first time, the caption of lblNum(0) is set to a random number. Then the loop runs again, with n increased to 1, so the caption of lblNum(1) gets set. The loop runs again with n=2 and then stops. For...Next loops are very useful when code has to be run repeatedly for a known number of times (if we don't know how many times the loop should run then we use use a Do...Loop).

Our program works OK, but doesn't behave much like a real slot machine. A real slot machine lets the number flash by for a random time before freezing each number, one by one. Let's try to simulate that. We will add a timer control called tmr1 to the form to make the numbers flash by. Set the interval property to 100 so that each caption will change 10 times every second (100 milliseconds = 0.1 second). Type this code for the timer control, then check that it makes the numbers change constantly:

Private Sub tmr1_Timer()
For n = 0 To 2
    lblNum(n).Caption = Int(10 * Rnd())
Next
End Sub

The For...Next loop ensures that each time the timer goes off all three labels are changed to show a new random number.

Now we need to figure out how to 'freeze' numbers in the labels after a random time that is different for each label. Let's say we want the first label to be frozen after 0-2 seconds, the second after 2-4 seconds and the third after 4-6 seconds. We will create an 'array' called delay to hold the three numbers. A normal variable can hold only a single variable, whereas an array can hold several. By adding the line

Dim delay(2)

in the General Declarations area (at the top of the code window, above all existing code) we create an array called delay that can hold three values (not two). The first value will be held in delay(0), the next in delay(1), the last in delay (2).

The following code in the command button can generate the desired random numbers and store them into the various parts of the array:

delay(0) = 2 * Rnd()
delay(1) = 2 + 2 * Rnd()
delay(2) = 4 + 2 * Rnd()

Now add a line to the command button to record when the button was pressed, using the Timer() function, which returns the number of seconds that have elapsed since midnight. So the complete code for the command button is:

Private Sub cmdSpin_Click()
starttime = Timer()
delay(0) = 2 * Rnd()
delay(1) = 2 + 2 * Rnd()
delay(2) = 4 + 2 * Rnd()
End Sub

Now we need to modify the timer code so that the timer stops changing each caption after its delay time has been exceeded. The code below can do the job:

Private Sub tmr1_Timer()
For n = 0 To 2
	If Timer() < starttime + delay(n) Then
		lblNum(n).Caption = Int(10 * Rnd())
	End If
Next
End Sub

Notice that we are wanting to use a single starttime variable in two different procedures, so we must not forget to include the line 

Dim starttime

in the General Declarations area, otherwise VB will create two different variables called starttime, one for each procedure.

The If line above determines when the caption of lblNum(n) should stop changing (starttime + delay) then checks whether the current time is below this value. If it is, then the caption is changed to a new random number, otherwise nothing happens.

As before, the For...Next loop makes sure that all three labels are checked each time the timer control goes off.

You might wonder why the timer code doesn't change the labels before the command button has been clicked for the first time - it won't do that because when VB creates the starttime variable variable in the Form_Load procedure it gives it an initial value of zero. It's very unlikely that the If line condition will be true, since the Timer() function would have to return a number less than the delay value, which could only happen within a couple of seconds of midnight (the Timer() function returns the number of seconds that have elapsed since midnight).

Thus your program should now be working fine - we just have to add code to detect 'winning combinations'. Let's give rewards for anyone who gets one or more sevens when they spin the numbers.

The following code will count how many sevens are in the three labels, and will give messages accordingly:

Private Sub tmr1_Timer()
For n = 0 To 2
	If Timer() < starttime + delay(n) Then
		lblNum(n).Caption = Int(10 * Rnd())
	ElseIf n = 2 Then
		checkwin
	End If
Next n
End Sub

Private Sub checkwin()
tmr1.Enabled = False
For n = 0 To 2
	sevenscount = sevenscount - (lblNum(n).Caption = "7")
Next n
If sevenscount Then
	MsgBox ("You scored " & sevenscount & " seven(s). Well done!")
End If
End Sub

For legibility, I created a new procedure called 'checkwin' which is activated when the timer code detects that the delay of the last label (n=2) has been exceeded. The checkwin procedure include a line that disables the timer, so you should add a line anywhere in the command button code to enable it again:

tmr1.Enabled = True

The checkwin procedure includes these interesting lines:

For n = 0 To 2
    sevenscount = sevenscount - (lblNum(n).Caption = "7")
Next n

The For...Next loop examines each label in turn while the sevenscount variable keeps track of the total number of sevens that have been found. Inside the parentheses is an expression which is either true or false. When forced to treat these conditions as numbers, VB always treats the 'true' condition as -1 and the 'false' condition as zero. 

Similarly, when forced to treat numbers as 'true' or 'false' conditions, VB treats all non-zero numbers as equivalent to 'true' and zero as equivalent to 'false', so you should be able to understand the line:

If sevenscount Then

Note that the sevenscount variable is NOT declared in the General Declarations. There is no need to declare it, for it is only used in one procedure. Also, because it is not declared, this variable 'forgets' its value each time the checkwin procedure ends. Try adding the sevenscount variable to the General Declarations and notice that the second time you have a winning combination the messagebox now gives the wrong value for the number of sevens since sevenscount does not reset to zero when the checkwin procedure terminates.

For EXTRA CREDIT, can you...

bulletmodify the checkwin code so that the user can also win by getting two digits that are the same
bulletincrease the number of labels to four or five and change the code as appropriate. This should not be too difficult as we have been using a control array and a variable array
bulletadd new features that you have thought of yourself
bulletadd a sound to your project...

Click HERE to see how easy it is to add sound to this (or any other) program, then add a cash register sound to your Jackpot program. Click HERE to download a sound file called 'cashreg.wav' and make sure you save it into the same folder that holds your project files. If left-clicking does not give you a file-save dialog then try right-clicking.

Place the function declaration (from the Sound project) into the General Declarations area, just above or just below the DIM line. Change the checkwin code to:

Private Sub checkwin()
For n = 0 To 2
	sevenscount = sevenscount - (lblNum(n).Caption = "7")
Next n
	If sevenscount Then
		rc = sndPlaySound(App.Path & "\cashreg.wav", 1)
		'MsgBox ("You scored " & sevenscount & " seven(s). Well done!")
	End If
End Sub

I've commented out the messagebox code so that the new sound is not drowned by the messagebox beep. Try the program and you should hear the cash register sound each time you win!

Before leaving this page, you should know that although we have used a control array in this project, and it may have made our code a little neater, we have not experienced the real power of control arrays, which is that all the controls in the array SHARE THE SAME CODE. This is a huge advantage as it can save much duplication of code, as we may see in a later project.

Previous Up Next