Creating a Bingo Game in .NET


When I was younger, I saw an advert about a Bingo club. The advert featured mostly elderly people enjoying a game of Bingo. Since then, when I heard the term "Bingo," I pictured only elderly people playing the game. Now, I enjoy the odd game of Bingo, and I am not old, so it's amazing what a small memory can do.

Anyway, today you will learn how to create a Bingo game in .NET. I hope you have fun.


Bingo is a game of probability. In Bingo, players mark off numbers on cards as the numbers are drawn randomly by a caller. The winner is the first person to mark off all his or her numbers. Bingo can be played with 90 balls or 75 balls, depending on where you are.


You will use either C# or Visual Basic.NET to create a Bingo card, then pick the random numbers. Open Visual Studio and create a Windows Forms application in your language of choice. Once the default form is displayed, add the following objects onto it:

  • 2 x Labels
  • 2 x Buttons
  • 1 x TableLayoutPanel

You may name these objects anything you like, although my names may be different than yours. Resize your Form's Height. An example screen is shown in Figure 1.

Figure 1: Design

Add the following fields and enumerations to your class.


   private int intRows = 18;

   private char[] chrHeader = new char[] { 'B', 'I', 'N', 'G',
      'O' };

   private int intMinHeight = 470;
   private int intMinWidth = 450;

   int intWidth = 0;
   int intHeight = 0;

   private int intTotalCells = 0;

   private int intCalledNumbers;

   private Dictionary<string, Label> dicCards = new
      Dictionary<string, Label>();

   private Random rndRand = new Random();

   enum ActiveState
      Active = -16744448,    // Green//

      InActive = -16711681   // Cyan//


   Private intRows As Integer = 18

   Private chrHeader() As Char = New Char() {"B"c, "I"c, "N"c, _
      "G"c, "O"c}

   Private intMinHeight As Integer = 470
   Private intMinWidth As Integer = 450

   Private intTotalCells As Integer = intRows * chrHeader.Length
   Private intCalledNumbers As Integer

   Private dicCards As New Dictionary(Of String, Label)

   Dim rndRand As New Random

   Enum ActiveState

      Active = -16744448     'Green'
      InActive = -16711681   'Cyan'

   End Enum

The Rows and Columns are created. The Height and Width of the gaming board is instantiated, and a dictionary object is created to store the cards. The ActiveState enumeration displays green or cyan, depending on whether the number has been called.

Add the following Function.


   public Label lblLabel()
      intWidth = (tblBingo.Width / chrHeader.Length) - 2;
      intHeight = (tblBingo.Height / (intRows + 1)) - 2;

      Label lbl = new Label();

      lbl.AutoSize = false;
      lbl.Width = intWidth;
      lbl.Height = intHeight;
      lbl.TextAlign = ContentAlignment.MiddleCenter;
      lbl.BorderStyle = BorderStyle.FixedSingle;
      lbl.Tag = ActiveState.InActive;

      return lbl;


   Public Function lblLabel() As Label

      Static intWidth As Integer = _
         (tblBingo.Width \ chrHeader.Length) - 2
      Static intHeight As Integer = _
         (tblBingo.Height \ (intRows + 1)) - 2

      Dim lbl As New Label

      lbl.AutoSize = False
      lbl.Width = intWidth
      lbl.Height = intHeight
      lbl.TextAlign = ContentAlignment.MiddleCenter
      lbl.BorderStyle = BorderStyle.FixedSingle
      lbl.Tag = ActiveState.InActive

      Return lbl

   End Function

The preceding Function creates a Label control object and sets its settings. You will create a label for each cell in the gaming board, which you will create now.


   private void frmBingo_Shown(object sender, EventArgs e)

      lblCurrent.TextAlign = ContentAlignment.MiddleRight;


      if (tblBingo.Width < intMinWidth)
         tblBingo.Width = intMinWidth;

         if (tblBingo.Height < intMinHeight)
            tblBingo.Height = intMinHeight;

            float sngColumns = System.Convert.ToSingle
               (100 / (double)chrHeader.Length);
            float sngRows = System.Convert.ToSingle
               (100 / (double)(intRows + 1));

            tblBingo.ColumnCount = chrHeader.Length;
            tblBingo.RowCount = intRows + 1;

            for (int idx = 0; idx <= chrHeader.Length - 1; idx++)

               tblBingo.ColumnStyles.Add(new ColumnStyle(SizeType
                  .Percent, sngColumns));

            for (int idx = 0; idx <= intRows; idx++)

               tblBingo.RowStyles.Add(new RowStyle(SizeType
                  .Percent, sngRows));

            for (int iCol = 0; iCol <= chrHeader.Length - 1;
               Label lbl = lblLabel();
               lbl.Text = chrHeader[iCol].ToString();

               tblBingo.Controls.Add(lbl, iCol, 0);

               for (int iRow = 1; iRow <= intRows; iRow++)
                  lbl = lblLabel();

                  lbl.Click += lblClick;

                  lbl.Text = chrHeader[iCol].ToString() + ' ' +
                     (iCol * intRows + iRow).ToString();

                  tblBingo.Controls.Add(lbl, iCol, iRow);
                  dicCards.Add(lbl.Text, lbl);




   Private Sub frmBingo_Shown(ByVal sender As Object, _
         ByVal e As System.EventArgs) Handles Me.Shown

      lblCurrent.TextAlign = ContentAlignment.MiddleRight


      If tblBingo.Width < intMinWidth Then tblBingo.Width = _
      If tblBingo.Height < intMinHeight Then tblBingo.Height = _

      Dim sngColumns As Single = CSng(100 / chrHeader.Length)
      Dim sngRows As Single = CSng(100 / (intRows + 1))

      tblBingo.ColumnCount = chrHeader.Length
      tblBingo.RowCount = intRows + 1

      For idx As Integer = 0 To chrHeader.Length - 1

         tblBingo.ColumnStyles.Add(New ColumnStyle(SizeType _
            .Percent, sngColumns))


      For idx As Integer = 0 To intRows

         tblBingo.RowStyles.Add(New RowStyle(SizeType.Percent, _


      For iCol As Integer = 0 To chrHeader.Length - 1

         Dim lbl As Label = lblLabel()
         lbl.Text = chrHeader(iCol)

         tblBingo.Controls.Add(lbl, iCol, 0)

         For iRow As Integer = 1 To intRows

            lbl = lblLabel()

            AddHandler lbl.Click, AddressOf lblClick

            lbl.Text = chrHeader(iCol) & " " & _
               (iCol * intRows + iRow).ToString

            tblBingo.Controls.Add(lbl, iCol, iRow)
            dicCards.Add(lbl.Text, lbl)




   End Sub

You determine the height and width each Bingo cell should be, and then add a label into it. Altogether, you will add 90 cells. You then add an event handler for each label object. You will add this event handler now.


   private void lblClick(System.Object sender, System.EventArgs e)




   Private Sub lblClick(ByVal sender As System.Object, _
         ByVal e As System.EventArgs)


   End Sub

Add the Populate sub procedure.


   private void Populate(System.Object sender)
      Label lbl = (Label)sender;

      if ((ActiveState)lbl.Tag == ActiveState.InActive)
         intCalledNumbers += 1;

         lbl.Tag = ActiveState.Active;
         lbl.BackColor = Color.FromArgb((int)ActiveState.Active);

         lblCurrent.Text = lbl.Text;
         lblAllPicks.Text = lblAllPicks.Text.Insert(0, " . " +

         if (lblAllPicks.Text.Length > 60)
            int iIndex = lblAllPicks.Text.LastIndexOf(" ");
            lblAllPicks.Text = lblAllPicks.Text.Substring(0,

         System.Drawing.Point dp = lbl.Location;

         dp.X += tblBingo.Location.X + 4;
         dp.Y += tblBingo.Location.Y + 4;

         Cursor.Position = PointToScreen(dp);


   Private Sub Populate(sender As System.Object)

      Dim lbl As Label = CType(sender, Label)

      If DirectCast(lbl.Tag, ActiveState) = ActiveState.InActive _

         intCalledNumbers += 1

         lbl.Tag = ActiveState.Active
         lbl.BackColor = Color.FromArgb(ActiveState.Active)

         lblCurrent.Text = lbl.Text
         lblAllPicks.Text = lblAllPicks.Text.Insert(0, " . " _
            & lbl.Text)

         If lblAllPicks.Text.Length > 60 Then

            Dim iIndex As Integer = _
               lblAllPicks.Text.LastIndexOf(" ")
            lblAllPicks.Text = lblAllPicks.Text.Substring(0, _

         End If

         Dim dp As Drawing.Point = lbl.Location

         dp.X += tblBingo.Location.X + 4
         dp.Y += tblBingo.Location.Y + 4

         Cursor.Position = PointToScreen(dp)

      End If

   End Sub

The Populate sub procedure fills in the cells, depending on their respective states. It also adds a dot next to the called number. If you were to run your project now, you might see a screen similar to Figure 2.

Game board
Figure 2: Game board

Add the code for the Pick and Reset buttons.


   private void btnPick_Click(object sender, EventArgs e)

      if (intCalledNumbers >= intTotalCells)

         lblCurrent.Text = "Game over";



      List<KeyValuePair<string, Label>> lstNotCalled;

      lstNotCalled = (from kvp in dicCards
                      where (ActiveState)kvp.Value.Tag ==
                      select kvp).ToList();

      if (lstNotCalled.Count > 0)

         int idx = rndRand.Next(lstNotCalled.Count);
         KeyValuePair<string, Label> foo = lstNotCalled[idx];




   private void btnReset_Click(object sender, EventArgs e)

      foreach (KeyValuePair<string, Label> kvp in dicCards)

         kvp.Value.BackColor =
         kvp.Value.Tag = ActiveState.InActive;


      intCalledNumbers = 0;

      lblCurrent.Text = "Reset";
      lblAllPicks.Text = "";




   Private Sub btnReset_Click(ByVal sender As System.Object, _
         ByVal e As System.EventArgs) Handles btnReset.Click

      For Each kvp As KeyValuePair(Of String, Label) In dicCards]

         kvp.Value.BackColor = Color.FromArgb(ActiveState.InActive)
         kvp.Value.Tag = ActiveState.InActive


      intCalledNumbers = 0

      lblCurrent.Text = "Reset"
      lblAllPicks.Text = ""


   End Sub

   Private Sub btnPick_Click(sender As System.Object, _
         e As System.EventArgs) Handles btnPick.Click

      If intCalledNumbers >= intTotalCells Then

         lblCurrent.Text = "Game over"

         Exit Sub

      End If

      Dim lstNotCalled As List(Of KeyValuePair(Of String, Label))

      lstNotCalled = (From kvp In dicCards Where _
         DirectCast(kvp.Value.Tag, ActiveState) = _
         ActiveState.InActive Select kvp).ToList

      If lstNotCalled.Count > 0 Then

         Dim idx As Integer = rndRand.Next(lstNotCalled.Count)
         Dim foo As KeyValuePair(Of String, Label) = _


      End If

   End Sub

A Random number gets picked and filled with Green inside the Pick button; Reset resets everything back to their default values. Instantiate the necessary objects inside the C# program's constructor.


   public frmBingo()

      intTotalCells = intRows * chrHeader.Length; ;


In Visual Basic, this step is not needed.

Your running program will look like Figure 3.

Figure 3: Running


Well, there you have it! Bingo is not too difficult to do, as with any other game. All you need is a bit of logic and time.

This article was originally published on October 5th, 2018

About the Author

Hannes DuPreez

Hannes du Preez is a self-taught developer who started learning to program in the days of QBasic. He has written several articles over the years detailing his programming quests and adventures. .NET is his second love, just after his wife and kid. He has always been an avid supporter of .NET since the beginning and is an expert in VB and C#. He was given the Microsoft Most Valuable Professional Award for .NET (2008–2017). He has worked as a moderator and an article reviewer on online forums and currently works as a C# developer and writes articles for CodeGuru.com, Developer.com, DevX.com, and the Database journal.
His first book Visual Studio 2019 In Depth is currently on sale on Amazon and Bpb Publications.

You could reach him at: ojdupreez1978[at]gmail[dot]com

Related Articles

Thanks for your registration, follow us on our social networks to keep up-to-date