| 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:
 | control arrays |
 | variable arrays |
 | For...Next loops |
 | the relationship between numbers and the conditions 'true' and 'false' |
 | random 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...
 | modify the checkwin code so that the user can also win by getting two
digits that are the same |
 | increase 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 |
 | add new features that you have thought of yourself |
 | add 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. |