Creating a Tile-Matching Game in VB.NET 2012

CodeGuru content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More.

Introduction

I love games; but I am in no sense of the word a gamer. My wife is the one and only gamer in my family. Also, the word gamer is quite relative. Why? Well, people think of gamers as young people with the best and biggest pcs playing games over the network with each other. This is not my wife, and most definitely not me. Our idea of fun is playing games such as mystery games, and tower defense games. We love having little in-house competitions (which I, strangely enough, win ). Games such as Angry Birds, Mystery P. I., Plants vs. Zombies, and Rise of Atlantis keep us busy through the night!

My wife always asks me if I could make a game or two (now over five) for her, and I always tend to agree to it. This next game I have tackled was a simple yet powerful Tile-matching game. This means that we have to match images that adjoin each other. This is what we’ll do today.

Design

Not much of a design. Start up Visual Studio 2012 and start a new Visual Basic Windows Forms project. Name it anything you want. Design your layout to resemble Figure 1:

Our Design
Figure 1 – Our Design

Code

First, our variables. Create the following objects inside your General Declarations section:

    Private arrImages(4) As Image 'Our pics

    Private RandGen As Random 'Random Number Generator
    Private RandIndex As Integer

    Dim PBTemp() As PictureBox 'Dynamic PictureBox
    Private intScore As Integer 'Score

    Private intPairsFound As Integer 'Total Items Found

    Private timeEnd As DateTime 'Calculates Ending Time
    Private timeDiff As TimeSpan 'Difference Between Start and End Times

Next, let us create our board, which will host our pictures:

    Public Sub DrawPBGrid() 'Draws Grid of 225 blocks - 15 x 15

        Dim NewLoc As New Point 'Location of Each New Block
        arrImages(0) = My.Resources.ant
        arrImages(1) = My.Resources.butterfly
        arrImages(2) = My.Resources.dragonfly
        arrImages(3) = My.Resources.ladybug
        arrImages(4) = My.Resources.mosquito
        RandGen = New Random(Now.Millisecond)

        For CurrRow As Integer = 0 To 14 'Row By Row

            For CurrCol As Integer = 0 To 14 'Column In Row By Column In Row


                NewLoc.X = 2 + CurrRow * 30 'Height Of Block
                NewLoc.Y = 2 + CurrCol * 30 'Width Of Block

                Dim PB As New PictureBox 'New picturebox
                ReDim Preserve PBTemp(CurrCol)

                With PB 'Set Properties
                    .Name = CurrRow.ToString() & "_" & CurrCol.ToString 'Name Ex: 1_2 ( Row 1 _ Col 2 )
                    .BorderStyle = BorderStyle.FixedSingle 'Block Effect
                    .Location = NewLoc 'Set Position
                    .Width = 30 'Width
                    .Height = 30 'Height
                    .BackColor = System.Drawing.Color.White 'BackColour
                    RandIndex = RandGen.Next(0, 5)
                    .Image = arrImages(RandIndex)

                    AddHandler PB.MouseClick, AddressOf PB_MouseClick 'Event Handler Click

                End With
                PBTemp(CurrCol) = New PictureBox
                PBTemp(CurrCol).Image = PB.Image
                Me.Controls.Add(PB) 'Add PBs

            Next

        Next

    End Sub

With the above sub, we produce 225 ( 15 x 15 ) blocks. These will host our pictures. We set each particular block’s properties and add a random picture into it via our random generators. Most importantly, we added an event handler so that we will be able to click on each of these dynamic pictureboxes during runtime. When this sub is called, and the program is run, it will produce the following screen.

Board
Figure 2 – Board

These pictures were added as resources, feel free to use them as well.

Add the next sub:

    Private Sub btnStart_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnStart.Click

        DrawPBGrid()


        timeEnd = DateTime.Now 'Get Current Time

        Dim minute As Double = System.Convert.ToDouble(5) '5 Minutes
        Dim second As Double = System.Convert.ToDouble(0) '0 Seconds

        timeEnd = timeEnd.AddMinutes(minute) 'Add Mintues
        timeEnd = timeEnd.AddSeconds(second) 'Add Seconds

        tmrLoop.Start()


    End Sub

This is the code for our start button. It sets everything in motion. It draws the gaming board, and starts the count down timer, which gives 5 minutes.

Now things start to become interesting. What we need to do now is to use the common PictureBox click event handler, to determine our matches. Add the next code:

    Private Sub PB_MouseClick(ByVal sender As Object, ByVal e As MouseEventArgs) 'Common Event Handler For PBs

        Static intCounter As Integer 'How Many Times Clicked?

        Static pb() As PictureBox 'Selected PictureBox(es)

        Static colname() As String 'Which Column Is PictureBox(es) In?

        Static rowname() As String 'Which Row Is PictureBox(es) In?

        ReDim Preserve pb(intCounter) 'Resize Arrays According To Size of intCounter
        ReDim Preserve colname(intCounter)
        ReDim Preserve rowname(intCounter)


        pb(intCounter) = New PictureBox 'New pictureBox

        pb(intCounter) = DirectCast(sender, PictureBox) 'Store Selected PictureBox

        'Obtain Column Name
        colname(intCounter) = pb(intCounter).Name.ToString.Substring(0, pb(intCounter).Name.ToString.LastIndexOf("_"))

        'Obtain Row Name
        rowname(intCounter) = pb(intCounter).Name.ToString.Substring(pb(intCounter).Name.ToString.LastIndexOf("_") + 1)

        If intCounter >= 1 Then 'If Clicked Twice

            If pb(intCounter - 1).Image Is pb(intCounter).Image Then 'If Clicked Pictures Are The Same

                'If Pictures In Same Row / Column
                If colname(intCounter - 1) = colname(intCounter) OrElse rowname(intCounter - 1) = rowname(intCounter) Then

                    pb(intCounter - 1).BackColor = Color.Black 'Indicate Match
                    pb(intCounter).BackColor = Color.Black

                    pb(intCounter - 1).Image = Nothing 'Clear Pictures
                    pb(intCounter).Image = Nothing

                    intScore += 20 'Update Score

                    lblScore.Text = intScore

                    intPairsFound += 1

                    Scramble() 'Scramble Pictures

                End If

            End If

        End If

        intCounter += 1 'Increase intCounter With Each Click

    End Sub

Not too difficult hey? Inside the above sub we have called the Scramble sub, let us add it now:

    Private Sub Scramble() 'Replace Pictures Randomly

        Dim RandGen As New Random(Now.Millisecond) 'Generate Random Number

        For Each P As PictureBox In Me.Controls.OfType(Of PictureBox)() 'Loop Through PictureBox Grid

            Dim RandIndex As Integer = RandGen.Next(0, 5) 'Generate New Random Picture

            If P.BackColor <> Color.Black Then 'Skip Found Pairs

                P.Image = arrImages(RandIndex) 'Replace Picture

            Else

                P.Image = Nothing

            End If
        Next

    End Sub

Quite straightforward. We loop through all of the pictureboxes on the form. We then replace all of the pictures randomly, except for the pairs that have already been found. Add the final events and subs:

    Private Sub ShowSummary() 'Shows Summary After Game Completion

        Dim strSummary As String 'Summary String

        'Compose String For Output
        strSummary = "Summary" & Environment.NewLine & Environment.NewLine & _
            "Pairs Found: " & intPairsFound.ToString & Environment.NewLine & Environment.NewLine & _
            "SCORE: " & intScore.ToString

        lblScore.Text = strSummary 'Write Text

    End Sub

    Private Sub tmrLoop_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tmrLoop.Tick

        Dim strFinalOutput As String 'Output String

        timeDiff = timeEnd - DateTime.Now

        'Caclulate Difference Between Start and End
        Dim output As TimeSpan = New TimeSpan(timeDiff.Hours, timeDiff.Minutes, timeDiff.Seconds)

        strFinalOutput = "Time Left: " & output.ToString().Substring(3) 'Concatenates Time

        lblTime.Text = strFinalOutput

        If (timeDiff.Ticks < 0) Then 'If Time is Up

            tmrLoop.Stop()
            MessageBox.Show("Time's UP!!")
            ShowSummary()
            btnStart.Enabled = True
        End If
    End Sub

    Private Sub btnEnd_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnEnd.Click

        tmrLoop.Stop() 'Stop Timer

        ShowSummary() 'Show Summary

    End Sub

The ShowSummary sub is responsible for displaying our score, once the game is over or has been stopped. The tmrLoop_Tick event counts down the time (5 minutes we set up inside btnStart_Click). btnEnd stops the game and produces a score summary.

If you were to run this game now, you’d be able to select matching pairs. After a pair has been identified, that pair will turn black and the images will shuffle. This makes things a bit more interesting for the player, and a bit more difficult to match all the pairs. Your game play screen will look something like Figure 3.

Playing the game
Figure 3 – Playing the game

Conclusion

I am including the source code in zipped format below, just in case you have lost your way somehow. I hope you have enjoyed creating this simple yet powerful game and that you have benefited from it. Until next time, cheers!

Hannes DuPreez
Hannes DuPreez
Ockert J. du Preez is a passionate coder and always willing to learn. He has written hundreds of developer articles over the years detailing his programming quests and adventures. He has written the following books: Visual Studio 2019 In-Depth (BpB Publications) JavaScript for Gurus (BpB Publications) He was the Technical Editor for Professional C++, 5th Edition (Wiley) He was a Microsoft Most Valuable Professional for .NET (2008–2017).

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read