Creating a Visual Basic Hangman Game

Introduction

One of my all-time favourite games has to be Hangman. It wins loose-hands… Pardon the pun. As many of you may know, I am not the biggest gamer—not like Hangman can be classified as a gamer’s game, but still, it takes a lot for me to actually sit down and play a game. I suppose time is a big factor.

Today, you will learn how to create a basic Hangman game with Visual Basic.

For the uninformed…

Hangman

Hangman is a guessing game usually played with pencil and paper by two or more players. One player thinks of a word, phrase, or sentence and the other tries to guess the correct word, phrase, or sentence by suggesting letters, within a certain number of guesses.

The word, phrase, or sentence to guess is usually represented by a row of dashes, each representing a letter of the phrase. If the guessing player suggests a letter that occurs in the word, the other player should write the letter in all its correct positions. If the suggested letter or number does not occur in the word, the other player should draw one element of a hanged man stick figure as a tally mark.

Our Project

Start Visual Studio and create a new Visual Basic Windows Forms project.

Design

Design your form so that resembles Figure 1. You can name all your objects whatever you like, but keep in mind that my object names may differ from yours.

Our Design
Figure 1: Our Design

Code

Declare the following variables:

   Dim arrTerms() As String = {"Mercedes", "Audi", _
      "BMW", "Mazda", "Volkswagen"}

   Dim rndRandom As New Random

   Dim btnLetters() As Button

   Dim lstEnteredLetters As New List(Of Label)

   Dim blnSkip As Boolean

   Dim intStage As Integer = 0

arrTerms is an array that hosts the terms that will have to be guessed during the game. There could obviously be more arrays and more terms, but this article is only a quick introduction on how to create a hangman game with Visual Basic.

rndRandom is a Random object that will assist in picking an item from the preceding array. btnLetters is a dynamic button and will aid in giving the existing buttons a consolidated event handler. lstEnteredLetters is a List of label objects. Whatever letter gets chosen by the user will have to be displayed.

blnSkip allows you to skip an already selected letter. intStage indicates the game’s progress and, depending on the Stage the game is in, the hangman will be drawn at that level.

Add the Form_Load event:

   Private Sub Form1_Load(sender As Object, e As EventArgs) _
      Handles MyBase.Load

      Me.DoubleBuffered = True

      btnLetters = Me.Controls.OfType(Of Button).Except(New Button() _
         {btnNew}).ToArray

      Array.ForEach(btnLetters, Sub(b) AddHandler b.Click, _
         AddressOf btn_click)

      Reset()

   End Sub

Setting the DoubleBuffered property of any control reduces the flickering that gets caused by progressive redrawing of parts of a displayed surface. btnLetters contains all the alphabetic buttons, and then an event handler gets added that handles the Click events for each of the buttons. Lastly, a Sub named Reset is called, which we will add later.

Add the btn_Click event to handle all the click events from the alphabetic buttons:

   Private Sub btn_click(sender As Object, e As EventArgs)

      If blnSkip Then

         Return

      End If

      Dim btnTemp As Button = DirectCast(sender, Button)

      btnTemp.Enabled = False

      Array.ForEach(lstEnteredLetters.ToArray, Sub(lbl) lbl.Text = _
         If(lbl.Tag.ToString = btnTemp.Text, btnTemp.Text, lbl.Text))

      For x As Integer = 1 To lstEnteredLetters.Count - 1

         lstEnteredLetters(x).Left = lstEnteredLetters(x - 1).Right

      Next

      If lstEnteredLetters(lstEnteredLetters.Count - 1).Right > _
            Me.ClientSize.Width - 14 Then

         Me.SetClientSizeCore(lstEnteredLetters(lstEnteredLetters.Count _
            - 1).Right + 14, 381)

      End If

      intStage += If(Not lstEnteredLetters.Any(Function(lbl) lbl.Text = _
         btnTemp.Text), 1, 0)

      blnSkip = lstEnteredLetters.All(Function(lbl) lbl.Text <> _
         " ") OrElse intStage = 10

      Me.Invalidate()

   End Sub

If a letter has already been selected, nothing must happen. In other words: The button must be skipped. Once a button has been pressed, the item gets added to the lstEnteredLetters list. After the selected button’s text has been added to the lstEnteredLetters list, the letter gets displayed on the dynamically created label, and the width of the Letters’ display area gets dynamically adjusted to compensate for the width of the entered letter.

Add the Reset sub:

   Private Sub Reset()

      SetClientSizeCore(403, 486)

      Dim strTerm As String = arrTerms(rndRandom.Next(0, _
         arrTerms.Length)).ToUpper

      Array.ForEach(Me.Controls.OfType(Of Label).ToArray, _
         Sub(lbl) lbl.Dispose())

      Array.ForEach(btnLetters, Sub(b) b.Enabled = True)

      lstEnteredLetters = New List(Of Label)

      Dim intX As Integer = 14

      For Each c As Char In strTerm

         Dim lblTemp As New Label

         lblTemp.Text = " "
         lblTemp.Font = New Font(Me.Font.Name, 18, _
            FontStyle.Underline)
         lblTemp.Location = New Point(intX, 250)

         lblTemp.Tag = c.ToString
         lblTemp.AutoSize = True

         Controls.Add(lblTemp)
         lstEnteredLetters.Add(lblTemp)
         intX = lblTemp.Right

      Next

      blnSkip = False

      intStage = 0

      Me.Invalidate()

   End Sub

The Reset sub simply returns all the variables to their default values and disposes the event handlers created during execution of the program. Also, it creates and formats the labels according the text inside the Terms array.

Add the following code for the ‘New‘ button that restarts the game by calling Reset:

   Private Sub Button1_Click(sender As Object, e As EventArgs) _
         Handles btnNew.Click

      Reset()

   End Sub

Add the last part of code, which is the Form’s Paint event:

   Private Sub Form1_Paint(ByVal sender As Object, ByVal e As _
      System.Windows.Forms.PaintEventArgs) Handles Me.Paint

      If intStage >= 1 Then

         e.Graphics.DrawLine(New Pen(Color.Black, 2), 85, 190, 210, 190)

      End If

      If intStage >= 2 Then

         e.Graphics.DrawLine(New Pen(Color.Black, 2), 150, 190, 150, 50)

      End If

      If intStage >= 3 Then

         e.Graphics.DrawLine(New Pen(Color.Black, 2), 150, 50, 198, 50)

      End If

      If intStage >= 4 Then

         e.Graphics.DrawLine(New Pen(Color.Black, 2), 198, 50, 198, 70)

      End If

      If intStage >= 5 Then

         e.Graphics.DrawEllipse(New Pen(Color.Blue, 2), _
            New Rectangle(188, 70, 20, 20))

      End If

      If intStage >= 6 Then

         e.Graphics.DrawLine(New Pen(Color.Blue, 2), 198, 90, 198, 130)

      End If

      If intStage >= 7 Then

         e.Graphics.DrawLine(New Pen(Color.Blue, 2), 198, 95, 183, 115)

      End If

      If intStage >= 8 Then

         e.Graphics.DrawLine(New Pen(Color.Blue, 2), 198, 95, 213, 115)

      End If

      If intStage >= 9 Then

         e.Graphics.DrawLine(New Pen(Color.Blue, 2), 198, 130, 183, 170)

      End If

      If intStage >= 10 Then

         e.Graphics.DrawLine(New Pen(Color.Blue, 2), 198, 130, 213, 170)

      End If

   End Sub

Depending on the number of guesses, the progress of the game is shown in the form of drawn objects that create the gallows and the man and his limbs. Because the Form keeps repainting itself, you have to ensure that the previously drawn stages are continuously shown.

Our game in action:

Game Play
Figure 2: Game Play

Conclusion

Making games improves your logic tremendously. Although there was not much coding involved, there was still some complicated logic. I hope you have enjoyed today’s article.

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