7-2
RadioButton controls
GroupBo
x controls
Timer
control
Button
controls
7-3
On the left is the photo display area for Match Game. Each photo is displayed in
a picture box control. On the right are label controls used to display scoring.
There are also three group box controls and two button controls. Each group box
holds radio button controls used to establish game options. The two button
controls are used to start and stop the game and to exit the program. Below the
form in the tray area is a timer control used to implement delays.
Run the project (press <F5>). The game will appear in its stopped state, the
picture boxes holding photos are covered and waiting for you to choose game
options. You can choose one or two players. If one player, you can choose to
play alone or against the computer. If playing the computer, you can choose
how smart you want the computer to be (Difficulty). As options are selected, the
labels used for scoring change their headings to match the selections. Ive
selected a one player game, against the computer with a Hard difficulty:
7-4
Click the Start Game button to start playing. Its caption will change (now
reading Stop Game) and the options group boxes and Exit button will become
disabled. The message area says Pick a Box. When playing the computer, you
go first.
In this state, you pick two boxes to see what photos are behind them. If there is
a match, a tada sound will be heard, the boxes are removed, your score
incremented and you are given another turn. If there is no match, a different
sound is heard, the boxes are recovered and it becomes the computers turn.
Play continues in this manner (alternating turns) until all the matching photos
are found or until the Stop Game button is clicked. Play is similar for a two
player game, alternating turns between the two people playing. For a one player
game, playing alone, the computer keeps track of how many tries it takes you to
find all 10 pairs of photos.
7-5
Its the Seattle Space Needle and some pretty mountains; nice photos, but not a
match. I hear a boing sound and the board returns to its covered state. You
will most likely see different photos when you run the game because we are
using random numbers.
7-6
Its Seattles Pike Place Market and some blue mountains not a match. But,
Ive just seen those mountains.
7-7
Picking the second box in the top row and the second box in the bottom row, I
get a match. The photos are removed, my score is incremented and its my turn
again:
7-8
The game continues in this same manner, alternating turns between you and the
computer. When there is a match, you or the computer get an additional turn. I
continued playing this game against a pretty smart computer. Once all the
matches were found, the final score was me 5 and the computer 5, a tie!
Notice the game returns to its stopped state to allow another game or to stop
the program by clicking Exit.
Continue playing the game to understand its operation. Try using the two player
game and the one player game where you Play Alone. Or, in the one player
game against the computer, try different levels of difficulty. You will find at the
Hardest level, the computer is nearly impossible to beat. Click Exit when youre
done to stop the game. Open the code window and skim over the code, if you
like.
7-9
You will now build this project in stages. As you build Visual Basic Express
projects, we always recommend taking a slow, step-by-step process. It
minimizes programming errors and helps build your confidence as things come
together in a complete project.
We address form design. We discuss the controls needed to build the form,
establish initial control properties (including using your own photos in the game)
and discuss how to change the state of the controls. And, we address code
design. We discuss how to display the pairs of pictures, check for a match,
handle multiple players, and decide how to make computer-generated moves.
We also discuss how to scramble the photos and the use of timer controls.
7-10
7-11
When done, the form should resemble this (again recall this is smaller than its
real size):
The picture box controls are used to display the photos. The label controls
display scores and provide messaging. The radio buttons establish game options.
The buttons (one to start and stop the game and one to exit the project) are
used to control operation of the game. The timer control will be used to
implement a delay for the computer player. Finally, there is a picture box
control behind the two button controls. It is used to store the cover picture
that hides the photos.
7-12
If any of the controls used in this project are unfamiliar, review the appropriate
material in Chapter 2 of these notes. Set the control properties using the
properties window:
Form1 Form:
Property Name
Name
Text
FormBorderStyle
StartPosition
Property Value
frmMatchGame
Match Game
Fixed Single
CenterScreen
Property Value
White
FixedSingle
150
100
StretchImage
Property Value
White
FixedSingle
150
100
StretchImage
Property Value
White
FixedSingle
150
100
StretchImage
Property Value
White
FixedSingle
150
100
StretchImage
Property Value
White
FixedSingle
150
100
StretchImage
Property Value
White
FixedSingle
150
100
StretchImage
Property Value
White
FixedSingle
150
100
StretchImage
7-13
7-14
Property Value
White
FixedSingle
150
100
StretchImage
Property Value
White
FixedSingle
150
100
StretchImage
Property Value
White
FixedSingle
150
100
StretchImage
Property Value
White
FixedSingle
150
100
StretchImage
Property Value
White
FixedSingle
150
100
StretchImage
Property Value
White
FixedSingle
150
100
StretchImage
Property Value
White
FixedSingle
150
100
StretchImage
Property Value
White
FixedSingle
150
100
StretchImage
7-15
7-16
Property Value
White
FixedSingle
150
100
StretchImage
Property Value
White
FixedSingle
150
100
StretchImage
Property Value
White
FixedSingle
150
100
StretchImage
Property Value
White
FixedSingle
150
100
StretchImage
Property Value
White
FixedSingle
150
100
StretchImage
Label1 Label:
Property Name
Name
AutoSize
BorderStyle
Font Style
Font Size
Text
TextAlign
Property Value
lblPlayer1
False
None
Bold
12
Player 1
TopCenter
Label2 Label:
Property Name
Name
AutoSize
BackColor
BorderStyle
Font Size
Text
TextAlign
Property Value
lblScore1
False
White
Fixed3D
12
0
MiddleCenter
Label3 Label:
Property Name
Name
AutoSize
BorderStyle
Font Style
Font Size
Text
TextAlign
Property Value
lblPlayer2
False
None
Bold
12
Player 1
TopCenter
7-17
7-18
Label4 Label:
Property Name
Name
AutoSize
BackColor
BorderStyle
Font Size
Text
TextAlign
Property Value
lblScore2
False
White
Fixed3D
12
0
MiddleCenter
Label5 Label:
Property Name
Name
AutoSize
BackColor
BorderStyle
Font Size
Font Style
Text
TextAlign
Property Value
lblMessage
False
Light Yellow
Fixed3D
10
Bold
[blank]
MiddleCenter
Property Value
grpNumberPlayers
Light Cyan
9
Number of Players
Property Value
rdoTwoPlayers
9
Two Players
True
Property Value
rdoOnePlayer
9
One Player
Property Value
grpPlayWho
Light Cyan
9
Play Who?
Property Value
rdoPlayAlone
9
Play Alone
True
Property Value
rdoPlayComputer
9
Play Computer
Property Value
grpDifficulty
Light Cyan
9
Difficulty
7-19
7-20
Property Value
rdoEasiest
9
Easiest
True
Property Value
rdoEasy
9
Easy
Property Value
rdoHard
9
Hard
Property Value
rdoHardest
9
Hardest
Button1 Button:
Property Name
Name
Font Size
Text
Property Value
btnStartStop
10
Start Game
Button2 Button:
Property Name
Name
Font Size
Text
Property Value
btnExit
10
Exit
SizeMode
Width
Height
Visible
Property Value
picCover
cover.wmf (included in the
KidGamesVBE\KidGamesVBE Projects\Match
Game folder)
StretchImage
150
100
False
Timer1 Timer:
Property Name
Name
Interval
Property Value
timDelay
1000
7-21
7-22
This completes the form design (note the hidden picture box). You should be
able to identify all the controls in the game. Before looking at the code, lets
see how to select the photos used in the game.
7-23
We will use these samples to demonstrate the steps needed to select photos.
And, these photos are used through the rest of this chapter to demonstrate game
play.
The ten photos used in the game must be placed in the first ten picture boxes
(PictureBox1 through PictureBox10) of the Match Game form. So, we
sequentially set the Image property for each of these 10 picture boxes using 10
different photos.
7-24
To set a single Image property, select the corresponding picture box, select the
Image property and click the ellipsis () next to the property name. A Select
Resource window will appear. Select Local resource, then click the Import
button. An Open file dialog will appear. Navigate to your selected picture.
Here Ive chosen the included sample photo clara.jpg:
7-25
7-26
Repeat the above process for the nine other picture boxes and youre set. When
Im done setting the Image property for the 10 picture boxes using my photos,
my final form looks like this:
Of course, your final form will look different since you will be using your photos.
We will now begin writing code for the game. After writing code for the first
two projects, Safecracker and Tic Tac Toe, you should know there are certain
standard steps needed to get a working project. Since you should be familiar
with these steps by now, in discussing the code for Match Game, we will
combine some steps to speed up the coding process.
We will write the code in several steps. As a first step, we will write the code
that initializes the game. Then, we look at going from stopped state to
playing state and back. During the code development process, recognize you
may modify a particular procedure several times before arriving at the finished
product.
7-27
7-28
PhotoBox(19) = PictureBox19
PhotoBox(20) = PictureBox20
'image array
For I = 1 To 10
Photo(I) = PhotoBox(I).Image
Next
'initialize boxes
For I = 1 To 20
PhotoBox(I).Image = picCover.Image
Next
lblScore(1) = lblScore1
lblScore(2) = lblScore2
grpPlayWho.Enabled = False
grpDifficulty.Enabled = False
End Sub
Even though we have written minimal code, we can run the project to make sure
the form is properly initialized. Do this and youll see in the stopped state
(using default properties), the Match Game looks like this:
7-29
As desired, the game initializes in Two Players mode. The picture box controls
are all covered. We have three choices at this point: change to One Player
mode, click btnStartStop (the button with Start Game) or click btnExit (the
button with Exit).
If we click on the One Player button, different options are available and the
labels displaying the scoring information must change. The following must
happen:
Enable the grpPlayWho group box.
Set lblPlayer1.Text to You.
If Play Alone option is selected, set lblPlayer2.Text to Guesses, disable
grpDifficulty.
If Play Computer option is selected, set lblPlayer2.Text to Computer,
enable grpDifficulty.
The code corresponding to these steps is placed in the rdoOnePlayer Click event
procedure:
Private Sub rdoOnePlayer_Click(ByVal sender As
System.Object, ByVal e As System.EventArgs) Handles
rdoOnePlayer.Click
grpPlayWho.Enabled = True
lblPlayer1.Text = "You"
If rdoPlayAlone.Checked Then
lblPlayer2.Text = "Guesses"
grpDifficulty.Enabled = False
Else
lblPlayer2.Text = "Computer"
grpDifficulty.Enabled = True
End If
End Sub
7-30
In one player mode, we can select Play Alone or Play Computer. If a user clicks
Play Alone, we need to make sure grpDifficulty is disabled and that the Text
property of lblPlayer2 reads Guesses. Use this code in the rdoPlayAlone Click
event procedure:
Private Sub rdoPlayAlone_Click(ByVal sender As
System.Object, ByVal e As System.EventArgs) Handles
rdoPlayAlone.Click
grpDifficulty.Enabled = False
lblPlayer2.Text = "Guesses"
End Sub
Conversely, if a user clicks Play Computer, we need to make sure grpDifficulty
is enabled and that the Text property of lblPlayer2 reads Computer. Use this
code in the rdoPlayComputer Click event procedure:
Private Sub rdoPlayComputer_Click(ByVal sender As
System.Object, ByVal e As System.EventArgs) Handles
rdoPlayComputer.Click
grpDifficulty.Enabled = True
lblPlayer2.Text = "Computer"
End Sub
Lastly, we need code for the rdoTwoPlayers Click event to return to two player
mode. When this button is clicked, we disable grpPlayWho and grpDifficulty
and return the label headers to their default values:
Private Sub rdoTwoPlayers_Click(ByVal sender As
System.Object, ByVal e As System.EventArgs) Handles
rdoTwoPlayers.Click
grpPlayWho.Enabled = False
grpDifficulty.Enabled = False
lblPlayer1.Text = "Player 1"
lblPlayer2.Text = "Player 2"
End Sub
7-31
What about code for clicking on either of the two button controls (Start Game or
Exit)? The code for exiting is simple. The btnExit Click event:
Private Sub btnExit_Click(ByVal sender As System.Object,
ByVal e As System.EventArgs) Handles btnExit.Click
Me.Close()
End Sub
This simply says whenever the Exit button is clicked, the project closes. Add this
code to the code window.
The code for the btnStartStop button is much more complicated. We will build
it in several steps. First, we look at changing the form from stopped to
playing and back to stopped state. Before doing this, lets make sure our new
initialization code is working. Save and run the project. It will be in two player
mode. Click One Player; you should see:
Notice the label controls change. The Play Who? group box is enabled and the
Difficulty group box is disabled.
7-32
Now, click Play Computer and the label controls again change and the Difficulty
group box is enabled:
Finally, make sure when you click Two Players, the form returns to two player
mode.
Were nearly ready to begin looking at the code behind the Start Game button.
A key step in starting this game is to hide two copies of each photo behind the
20 picture box controls. There are 10 photos, represented in the array Photo,
with indices from 1 to 10. We want to randomly place two copies of each index
in another array (with 20 elements). The elements of this second array tell us
which photo is behind which picture box control. We need some way to shuffle
integer indices around. This is actually a very common game task which can be
used for shuffling cards, selecting multiple choice answers, or here to hide
photos. We will build a general function to perform this task.
7-33
7-34
7-35
Add the NRandomIntegers function to your Match Game project. It will be used
to hide the 10 photos behind the 20 picture box controls. In the project, we will
use a form level array PhotoIndex (dimensioned to 20) to hold the randomly
sorted integers (the shuffled photo indices). Add this declaration to your
project:
Dim PhotoIndex(20) As Integer
The snippet of code that does a shuffle (and adjusts the values greater than 10)
is:
PhotoIndex = NRandomIntegers(20)
For I = 1 To 20
If PhotoIndex(I) > 10 Then PhotoIndex(I) -= 10
Next
Lets look at an example of how this works. If I run this snippet of code through
a little example, the 20 elements of PhotoIndex returned from one particular
call to NRandomIntegers are (arranged like our photo boxes):
17
8
7
18
10
13
12
14
4
3
6
19
9
20
1
16
15
11
5
2
You should see all the integers from 1 to 20. Now, subtracting 10 from each
value greater than 10 yields:
7
8
7
8
10
3
2
4
4
3
6
9
9
10
1
6
5
1
5
2
As desired, we now have random pairs of the integers from 1 to 10. Matching
pairs of integers represent matching pairs of photos in Match Game.
7-36
How do we know what photo is behind what picture box control? Say we have a
picture box control, represented by element i of the control array PhotoBox(i).
To determine the photo, examine PhotoIndex(i); call this value j. The photo
behind this picture box is then Photo(j), element j of the array holding the 10
photos being used. To set the Image property, the proper line of code is:
PhotoBox(i).Image = Photo(PhotoIndex(i))
We can now use the shuffling function to start building the code behind the
btnStartStop control.
7-37
Conversely, when the user clicks the Stop Game button in playing state,
several things must happen to switch Match Game to stopped state:
7-38
First, lets look at the code to start the game. We establish several variables in
the general declarations to help keep track of where we are in the game:
Dim PhotosRemaining As Integer, Score(2) As Integer
Dim PhotoFound(20) As Boolean
Dim PlayerNumber As Integer, ChoiceNumber As Integer,
Choice(2) As Integer
Dim CanClick As Boolean = False
Dim GameOver As Boolean
PhotosRemaining tells us how many photos are still hidden, while the Score
array holds the two players scores (number of matched photos found). The
PhotoFound array tells us whether a photo behind the corresponding picture box
control has been uncovered (so it cant be clicked twice). PlayerNumber tells us
whose turn it is and ChoiceNumber tells whether it is the players first choice on
the playing board or second choice. The Choice array holds the indices of the
two picture boxes selected. CanClick is used to determine if its okay to click on
the picture box controls. It is True when playing, False (the initial value) when
stopped. Finally, GameOver is used to tell us whether the game is actually over
(True if all photos uncovered) or the Stop Game button was clicked before
completing a game (False).
The code for the btnStartStop Click event that implements the steps for clicking
on Start Game and initializes the new variables is:
Private Sub btnStartStop_Click(ByVal sender As
System.Object, ByVal e As System.EventArgs) Handles
btnStartStop.Click
Dim I As Integer
If btnStartStop.Text = "Start Game" Then
btnStartStop.Text = "Stop Game"
Score(1) = 0
Score(2) = 0
lblScore(1).Text = "0"
lblScore(2).Text = "0"
PhotosRemaining = 20
PhotoIndex = NRandomIntegers(20)
For I = 1 To PhotosRemaining
If PhotoIndex(I) > 10 Then PhotoIndex(I) -= 10
PhotoFound(I) = False
PhotoBox(I).Image = picCover.Image
PhotoBox(I).Visible = True
Next
PlayerNumber = 1
ChoiceNumber = 1
7-39
If rdoTwoPlayers.Checked Then
lblMessage.Text = "Player 1, Pick a Box"
Else
lblMessage.Text = "Pick a Box"
End If
grpNumberPlayers.Enabled = False
grpPlayWho.Enabled = False
grpDifficulty.Enabled = False
btnExit.Enabled = False
CanClick = True
GameOver = False
Else
stop game
End If
End Sub
The steps follow should be clear. Note especially where the shuffling routine
was used to form the PhotoIndex array.
7-40
Save and run the project. Click on Start Game and you should see:
The only noticeable change is the two player message in the label control
(Player 1, Pick a Box). Stop the project (you cant click Stop Game yet) and try
the other options if youd like.
7-41
The code for the btnStartStop Click event that implements the steps for clicking
on Stop Game is (additions are shaded):
Private Sub btnStartStop_Click(ByVal sender As
System.Object, ByVal e As System.EventArgs) Handles
btnStartStop.Click
Dim I As Integer
If btnStartStop.Text = "Start Game" Then
btnStartStop.Text = "Stop Game"
Score(1) = 0
Score(2) = 0
lblScore(1).Text = "0"
lblScore(2).Text = "0"
PhotosRemaining = 20
PhotoIndex = NRandomIntegers(20)
For I = 1 To 20
If PhotoIndex(I) > 10 Then PhotoIndex(I) -= 10
PhotoFound(I) = False
PhotoBox(I).Image = picCover.Image
PhotoBox(I).Visible = True
Next
PlayerNumber = 1
ChoiceNumber = 1
If rdoTwoPlayers.Checked Then
lblMessage.Text = "Player 1, Pick a Box"
Else
lblMessage.Text = "Pick a Box"
End If
grpNumberPlayers.Enabled = False
grpPlayWho.Enabled = False
grpDifficulty.Enabled = False
btnExit.Enabled = False
CanClick = True
GameOver = False
Else
btnStartStop.Text = "Start Game"
grpNumberPlayers.Enabled = True
If rdoOnePlayer.Checked Then
grpPlayWho.Enabled = True
If rdoPlayComputer.Checked Then
grpDifficulty.Enabled = True
End If
End If
btnExit.Enabled = True
CanClick = False
If Not (GameOver) Then
lblMessage.Text = "Game Stopped"
7-42
End If
End If
End Sub
Notice how we determine which group boxes should be disabled/enabled and
how we decide if the Game Stopped message is used. Other messages will
appear (developed in later code) if a game is played to completion (GameOver is
True).
Save and run the project. You should be able to now move from stopped to
playing state and back. Make sure the proper group boxes appear for the one
and two player options. Lets write the code for the two player game, first
looking at how to display a photo following a click on a picture box control.
7-43
7-44
7-45
Next
'initialize boxes
For I = 1 To 20
PhotoBox(I).Image = picCover.Image
Next
lblScore(1) = lblScore1
lblScore(2) = lblScore2
grpPlayWho.Enabled = False
grpDifficulty.Enabled = False
MatchSound = New
System.Media.SoundPlayer(Application.StartupPath +
"\tada.wav")
NoMatchSound = New
System.Media.SoundPlayer(Application.StartupPath +
"\boing.wav")
GameOverSound = New
System.Media.SoundPlayer(Application.StartupPath +
"\wow.wav")
End Sub
Add this procedure (PhotoBox_Click) to your project. This implements the
needed steps to accept a players selection of photo pairs:
Private Sub PhotoBox_Click(ByVal sender As System.Object,
ByVal e As System.EventArgs) Handles PictureBox1.Click,
PictureBox9.Click, PictureBox8.Click, PictureBox7.Click,
PictureBox6.Click, PictureBox5.Click, PictureBox4.Click,
PictureBox3.Click, PictureBox20.Click, PictureBox2.Click,
PictureBox19.Click, PictureBox18.Click,
PictureBox17.Click, PictureBox16.Click,
PictureBox15.Click, PictureBox14.Click,
PictureBox13.Click, PictureBox12.Click,
PictureBox11.Click, PictureBox10.Click
'determine which box was clicked
Dim ClickedBox As PictureBox, BoxNumber As Integer
ClickedBox = CType(sender, PictureBox)
'BoxNumber is number after PictureBox in name
BoxNumber = Val(Mid(ClickedBox.Name, 11,
Len(ClickedBox.Name) - 10))
If Not (CanClick) Or PhotoFound(BoxNumber) Then Exit Sub
'show image behind selected Photo box
PhotoBox(BoxNumber).Image = Photo(PhotoIndex(BoxNumber))
PhotoBox(BoxNumber).Refresh()
PhotoFound(BoxNumber) = True
If ChoiceNumber = 1 Then
Choice(1) = BoxNumber
ChoiceNumber = 2
7-46
If rdoTwoPlayers.Checked Then
lblMessage.Text = "Player " +
PlayerNumber.ToString() + ", Pick Another Box"
Else
'one player logic
End If
Else
Choice(2) = BoxNumber
ChoiceNumber = 1
If PhotoIndex(Choice(1)) = PhotoIndex(Choice(2)) Then
'a match
MatchSound.PlaySync()
PhotoBox(Choice(1)).Image = Nothing
PhotoBox(Choice(2)).Image = Nothing
Score(PlayerNumber) += 1
lblScore(PlayerNumber).Text =
Score(PlayerNumber).ToString
lblScore(PlayerNumber).Refresh()
PhotosRemaining -= 2
If PhotosRemaining = 0 Then
GameOver = True
GameOverSound.Play()
If rdoTwoPlayers.Checked Then
If Score(1) > Score(2) Then
lblMessage.Text = "Player 1 Wins!"
ElseIf Score(2) > Score(1) Then
lblMessage.Text = "Player 2 Wins!"
Else
lblMessage.Text = "It's a Tie!"
End If
Else
'one player logic
End If
btnStartStop.PerformClick()
Exit Sub
End If
'another turn
If rdoTwoPlayers.Checked Then
lblMessage.Text = "Player " +
PlayerNumber.ToString() + ", Pick Again"
Else
'one player logic
End If
Else
'no match
NoMatchSound.PlaySync()
PhotoFound(Choice(1)) = False
7-47
PhotoFound(Choice(2)) = False
PhotoBox(Choice(1)).Image = picCover.Image
PhotoBox(Choice(1)).Refresh()
PhotoBox(Choice(2)).Image = picCover.Image
PhotoBox(Choice(2)).Refresh()
'swap players
If rdoTwoPlayers.Checked Then
If PlayerNumber = 1 Then
PlayerNumber = 2
Else
PlayerNumber = 1
End If
lblMessage.Text = "Player " +
PlayerNumber.ToString() + ", Pick a Box"
Else
'one player logic
End If
End If
End If
End Sub
I know this is a lot of code to throw at you at once, but its simply a
straightforward implementation of the listed steps. Now that youre becoming a
great game programmer, you should be able to follow the logic. Its similar to
that used in the Tic Tac Toe game. Clicking any of the twenty picture controls
used to display photos will invoke this procedure. The first part of the code
determines the index of the element of picture box control array (PhotoBox)
that was clicked (the variable BoxNumber). If the box has already been clicked
(or CanClick is False), the procedure is exited. Otherwise, the photo behind the
selected box [Photo(PhotoIndex(BoxNumber))] is displayed. If this is the first
choice (ChoiceNumber = 1), we tell the player to pick again (using lblMessage).
Following display of the second choice, we look to see if the two selections
match. The selected boxes are stored in the Choice array. If there is a match,
the photos are removed, a sound is played and we check to see if all the photos
have been selected. If photos remain, the same player is given another turn.
Similarly, for no match, a sound is heard, the photos are recovered and players
are swapped. Notice sounds are played synchronously (PlaySync method). The
means the sound is completed before program execution continues. This adds a
nice little delay after the two photos are displayed.
7-48
All of this code is for a two player game. Notice, however, we have left hooks
(represented by comment statements) for later modifications for a one player
game.
Save and run the project. You and a friend should now be able to play a two
player version of Match Game. When a match is found, you will hear a tada
sound and the photos will disappear. When no match is found, you will hear a
boing sound and the photos will be recovered. When done, youll hear a crowd
saying wow. Give it a try. I played a two player game by myself. Heres the
form after three matches have been found (1 by Player 1, 2 by Player 2) and one
box has been uncovered:
7-49
Playing the game to completion, the form looks like this, where we could now
select other options and play again:
Player 2 wins! Actually, I was Player 1 and Player 2. In such a case, when you
dont have a playing partner, its fun to play alone or play the computer. Lets
code up those options now.
7-50
7-51
7-52
Else
lblMessage.Text = "It's a Tie!"
End If
Else
'one player logic
If rdoPlayAlone.Checked Then
lblMessage.Text = "All Matches Found!"
Else
'play computer logic
End If
End If
btnStartStop.PerformClick()
Exit Sub
End If
'another turn
If rdoTwoPlayers.Checked Then
lblMessage.Text = "Player " +
PlayerNumber.ToString() + ", Pick Again"
Else
'one player logic
If PlayerNumber = 1 Then
lblMessage.Text = "Pick a Box"
Else
'play computer logic
End If
End If
Else
'no match
NoMatchSound.PlaySync()
PhotoFound(Choice(1)) = False
PhotoFound(Choice(2)) = False
PhotoBox(Choice(1)).Image = picCover.Image
PhotoBox(Choice(1)).Refresh()
PhotoBox(Choice(2)).Image = picCover.Image
PhotoBox(Choice(2)).Refresh()
'swap players
If rdoTwoPlayers.Checked Then
If PlayerNumber = 1 Then
PlayerNumber = 2
Else
PlayerNumber = 1
End If
lblMessage.Text = "Player " +
PlayerNumber.ToString() + ", Pick a Box"
Else
'one player logic
If PlayerNumber = 1 Then
7-53
7-54
From here on, you just keep uncovering photos. The computer keeps track of
how many guesses (photos uncovered) it took you to find all the matches. Heres
the form once I finished (I didnt do real well it took me 58 guesses):
Now, lets see how to change the game to play against the computer.
7-55
So even at the highest level of difficulty, we allow that the computer can make a
mistake.
7-56
7-57
Code two empty functions (RandomChoice and SmartChoice) that return the
selected box for the random and smart computer options:
Private Function RandomChoice() As Integer
End Function
Private Function SmartChoice() As Integer
End Function
Well add some code to these soon.
Add a general procedure (ComputerTurn) that generates the computers
selection based on the selected difficulty and corresponding rules for move
generation:
Private Sub ComputerTurn()
Dim Threshold As Integer
If ChoiceNumber = 1 Then
Select Case Difficulty
Case 1
Threshold = 25
Case 2
Threshold = 50
Case 3
Threshold = 75
Case 4
Threshold = 90
End Select
If MyRandom.Next(100) < Threshold Then
SmartComputer = True
Else
SmartComputer = False
End If
End If
If SmartComputer Then
BoxSelected = SmartChoice()
Else
BoxSelected = RandomChoice()
End If
Call PhotoBox_Click(PhotoBox(BoxSelected), Nothing)
End Sub
7-58
In this code, if its the first choice (ChoiceNumber = 1), we decide whether we
have a smart computer for both computer selections. This is done by
establishing a Threshold (from 0 to 100) based on difficulty. The higher the
threshold, the smarter the computer. We then generate a random number from
0 to 99. If this number is less than the threshold, we use a smart computer
(SmartComputer is True). In such a case, the BoxSelected will be found using
the SmartChoice function (which has no code yet). If SmartComputer is False,
we obtain BoxSelected from the RandomChoice function (also empty). Once,
we know BoxSelected, we simulate a click on that box by calling the
PhotoBox_Click procedure with the proper argument.
Lastly, we need to modify the PhotoBox_Click procedure to allow a computer
opponent (recall the hooks are marked by comment statements). In a game
against the computer, the computer is Player 2 you always get to go first.
These shaded modifications simply call ComputerTurn at the proper time and
swap players when appropriate:
Private Sub PhotoBox_Click(ByVal sender As System.Object,
ByVal e As System.EventArgs) Handles PictureBox1.Click,
PictureBox9.Click, PictureBox8.Click, PictureBox7.Click,
PictureBox6.Click, PictureBox5.Click, PictureBox4.Click,
PictureBox3.Click, PictureBox20.Click, PictureBox2.Click,
PictureBox19.Click, PictureBox18.Click,
PictureBox17.Click, PictureBox16.Click,
PictureBox15.Click, PictureBox14.Click,
PictureBox13.Click, PictureBox12.Click,
PictureBox11.Click, PictureBox10.Click
'determine which box was clicked
Dim ClickedBox As PictureBox, BoxNumber As Integer
ClickedBox = CType(sender, PictureBox)
'BoxNumber is number after PictureBox in name
BoxNumber = Val(Mid(ClickedBox.Name, 11,
Len(ClickedBox.Name) - 10))
If Not (CanClick) Or PhotoFound(BoxNumber) Then Exit Sub
'one player/solitaire game
If rdoOnePlayer.Checked And rdoPlayAlone.Checked Then
Score(2) += 1
lblScore(2).Text = Score(2).ToString()
End If
'show image behind selected Photo box
PhotoBox(BoxNumber).Image = Photo(PhotoIndex(BoxNumber))
PhotoBox(BoxNumber).Refresh()
PhotoFound(BoxNumber) = True
If ChoiceNumber = 1 Then
Choice(1) = BoxNumber
7-59
ChoiceNumber = 2
If rdoTwoPlayers.Checked Then
lblMessage.Text = "Player " +
PlayerNumber.ToString() + ", Pick Another Box"
Else
'one player logic
If PlayerNumber = 1 Then
lblMessage.Text = "Pick Another Box"
Else
'play computer logic
lblMessage.Text = "Picking Another"
Call ComputerTurn()
Exit Sub
End If
End If
Else
Choice(2) = BoxNumber
ChoiceNumber = 1
If PhotoIndex(Choice(1)) = PhotoIndex(Choice(2)) Then
'a match
MatchSound.PlaySync()
PhotoBox(Choice(1)).Image = Nothing
PhotoBox(Choice(2)).Image = Nothing
Score(PlayerNumber) += 1
lblScore(PlayerNumber).Text =
Score(PlayerNumber).ToString
lblScore(PlayerNumber).Refresh()
PhotosRemaining -= 2
If PhotosRemaining = 0 Then
GameOver = True
GameOverSound.Play()
If rdoTwoPlayers.Checked Then
If Score(1) > Score(2) Then
lblMessage.Text = "Player 1 Wins!"
ElseIf Score(2) > Score(1) Then
lblMessage.Text = "Player 2 Wins!"
Else
lblMessage.Text = "It's a Tie!"
End If
Else
'one player logic
If rdoPlayAlone.Checked Then
lblMessage.Text = "All Matches Found!"
Else
'play computer logic
If Score(1) > Score(2) Then
lblMessage.Text = "You Win!"
7-60
7-61
PlayerNumber = 2
Else
PlayerNumber = 1
End If
End If
If PlayerNumber = 1 Then
lblMessage.Text = "Pick a Box"
Else
'play computer logic
lblMessage.Text = "Computer Picking"
ChoiceNumber = 1
Call ComputerTurn()
Exit Sub
End If
End If
End If
End If
End Sub
The framework is in place. If you trying running the game, the Two Player and
One Player, Play Alone options will still work. Playing against the computer will
not work because we need code for the RandomChoice and SmartChoice
procedures. Well do RandomChoice first.
7-62
7-63
We can test our random logic, but theres one problem. If (in ComputerTurn)
we select a smart computer, there is no code in the corresponding function
(SmartMove). To make things work, add this one line of code to the SmartMove
function:
Private Function SmartChoice() As Integer
Return (RandomChoice())
End Function
Were simply making the smart computer be random (temporarily) to allow
testing of the computer move logic.
Save and run the Match Game project. Select the One Player, Play Computer
options. Difficulty doesnt matter since all code is random at the moment.
Click Start Game. You go first, trying to find matching photos. Once its the
computers turn, notice two things. First, the photos are uncovered (in pairs)
randomly, very seldom do they match. Second, the photos appear and disappear
very quickly.
We can slow things down using the Timer control we established long ago.
Rather than immediately display the photos in the ComputerTurn procedure, we
will start the Timer control. We move the line of code that displays the photo
into the timers Tick event. With a 1000 millisecond Interval property, the
photos will remain on the form for 1 second. You may adjust this amount of
delay if you like. So, the timDelay Tick event procedure is:
Private Sub timDelay_Tick(ByVal sender As System.Object,
ByVal e As System.EventArgs) Handles timDelay.Tick
timDelay.Enabled = False
Call PhotoBox_Click(PhotoBox(BoxSelected), Nothing)
End Sub
Here we turn off the timer to stop the delay and display the photo with the line
of code moved from the ComputerTurn procedure.
7-64
Replace the last line in the ComputerTurn procedure (the call to the PhotoBox
click event) with the single shaded line that starts the timer control:
Private Sub ComputerTurn()
Dim Threshold As Integer
If ChoiceNumber = 1 Then
Select Case Difficulty
Case 1
Threshold = 25
Case 2
Threshold = 50
Case 3
Threshold = 75
Case 4
Threshold = 90
End Select
If MyRandom.Next(100) < Threshold Then
SmartComputer = True
Else
SmartComputer = False
End If
End If
If SmartComputer Then
BoxSelected = SmartChoice()
Else
BoxSelected = RandomChoice()
End If
timDelay.Enabled = True
End Sub
7-65
Save and run the game again. Select One Player and Play Computer. Again,
Difficulty does not matter. Click Start Game. You can now play against a
random computer. Youll see the computer is not that smart, making it pretty
easy for you to win. Well fix that next by coding up a far more intelligent and
formidable computer opponent. Heres a game I played (the computer did find
two matches the last two!):
7-66
7-67
PlayerNumber = 1
ChoiceNumber = 1
If rdoTwoPlayers.Checked Then
lblMessage.Text = "Player 1, Pick a Box"
Else
lblMessage.Text = "Pick a Box"
End If
grpNumberPlayers.Enabled = False
grpPlayWho.Enabled = False
grpDifficulty.Enabled = False
btnExit.Enabled = False
CanClick = True
GameOver = False
Else
btnStartStop.Text = "Start Game"
grpNumberPlayers.Enabled = True
If rdoOnePlayer.Checked Then
grpPlayWho.Enabled = True
If rdoPlayComputer.Checked Then
grpDifficulty.Enabled = True
End If
End If
btnExit.Enabled = True
CanClick = False
If Not (GameOver) Then
lblMessage.Text = "Game Stopped"
End If
End If
End Sub
The values in the Memory array are established in the PhotoBox Click event
procedure. The needed changes are shaded:
Private Sub PhotoBox_Click(ByVal sender As System.Object,
ByVal e As System.EventArgs) Handles PictureBox1.Click,
PictureBox9.Click, PictureBox8.Click, PictureBox7.Click,
PictureBox6.Click, PictureBox5.Click, PictureBox4.Click,
PictureBox3.Click, PictureBox20.Click, PictureBox2.Click,
PictureBox19.Click, PictureBox18.Click,
PictureBox17.Click, PictureBox16.Click,
PictureBox15.Click, PictureBox14.Click,
PictureBox13.Click, PictureBox12.Click,
PictureBox11.Click, PictureBox10.Click
'determine which box was clicked
Dim ClickedBox As PictureBox, BoxNumber As Integer
ClickedBox = CType(sender, PictureBox)
'BoxNumber is number after PictureBox in name
7-68
7-69
7-70
NoMatchSound.PlaySync()
PhotoFound(Choice(1)) = False
PhotoFound(Choice(2)) = False
PhotoBox(Choice(1)).Image = picCover.Image
PhotoBox(Choice(1)).Refresh()
PhotoBox(Choice(2)).Image = picCover.Image
PhotoBox(Choice(2)).Refresh()
'swap players
If rdoTwoPlayers.Checked Then
If PlayerNumber = 1 Then
PlayerNumber = 2
Else
PlayerNumber = 1
End If
lblMessage.Text = "Player " +
PlayerNumber.ToString() + ", Pick a Box"
Else
'one player logic
If rdoPlayComputer.Checked Then
If PlayerNumber = 1 Then
PlayerNumber = 2
Else
PlayerNumber = 1
End If
End If
If PlayerNumber = 1 Then
lblMessage.Text = "Pick a Box"
Else
'play computer logic
lblMessage.Text = "Computer Picking"
ChoiceNumber = 1
Call ComputerTurn()
Exit Sub
End If
End If
End If
End If
End Sub
7-71
Now, how do we use the Memory array to make a smart move? The rules we will
use for the computers two choices are:
Choice 1:
1. Check Memory array for a match.
2. If a match is found, select the first matching picture box.
3. If no match is found, select a random box.
Choice 2:
1. If a match was found with Choice 1, select the second matching picture
box.
2. If no match was found with Choice 1, check again for a match (the
random choice in Choice 1 may match a photo stored in memory).
3. If a match is found, select the matching picture box.
4. If no match is found, select a random box.
Lets implement this logic in code.
First, add the general function CheckForMatch. This function returns two
integers in an array. If these both of these integers are non-zero, it tells the
computer which two picture boxes have matching photos:
Private Function CheckForMatch() As Integer()
Dim I As Integer, J As Integer
Dim Matches(2) As Integer
Matches(1) = 0
Matches(2) = 0
For I = 1 To 20
For J = 1 To 20
If Memory(I) <> 0 And Memory(I) = Memory(J) And I <>
J Then
Matches(1) = I
Matches(2) = J
End If
Next
Next
Return (Matches)
End Function
This function does a simple comparison of all picture boxes looking for matching
non-zero values in the Memory array.
7-72
Add a general declaration for an integer array (MatchFound) that will be used to
store the matching picture boxes:
Dim MatchFound(2) As Integer
Now, remove the current Return statement from the SmartChoice function (the
one returning a random choice). Replace that function with this code which
implements the smart computer steps outlined above:
Private Function SmartChoice() As Integer
Dim SC As Integer
If ChoiceNumber = 1 Then
MatchFound = CheckForMatch()
If MatchFound(1) <> 0 And MatchFound(2) <> 0 Then
SC = MatchFound(1)
Else
SC = RandomChoice()
End If
Else
If MatchFound(1) <> 0 And MatchFound(2) <> 0 Then
SC = MatchFound(2)
Else
MatchFound = CheckForMatch()
If MatchFound(1) <> 0 And MatchFound(2) <> 0 Then
If MatchFound(1) <> Choice(1) Then
SC = MatchFound(1)
Else
SC = MatchFound(2)
End If
Else
SC = RandomChoice()
End If
End If
End If
Return (SC)
End Function
7-73
Save and run the project. The game is now fully functional. Try playing it
against the computer with the Hardest difficulty. You should find it is very hard
to beat. Continue playing seeing how the various levels of difficulty do indeed
adjust the computers intelligence. Heres a game I played with Hard difficulty.
I selected the first two boxes and see:
Its the Seattle Space Needle and some pretty mountains; nice photos, but not a
match.
7-74
Its Seattles Pike Place Market and some blue mountains not a match. But,
Ive just seen those mountains.
7-75
Picking the second box in the top row and the second box in the bottom row, I
get a match. The photos are removed, my score is incremented and its my turn
again:
7-76
Once all the matches were found, the final score was me 5 and the computer 5,
a tie!
7-77
7-78