Creating a Maze Game in .NET, Part 3: Adding the Final Touches to the Form

Introduction

If you have been following this series from the start, you will know that we have done a lot of work, more than I also expected, but it is most certainly going to be worth it. This part, the last part of this series, will add the usercontrol to the form and make it work from there.

If you haven’t followed the instructions set out in the first two parts of this series, please do so now. You can find the previous installments, “Creating a Maze Game in .NET, Part 1: Structure” and “Creating a Maze Game in .NET, Part 2: Adding Gameplay,” at these locations. If you are up to date with the series, well, let’s get cracking!

Add the following fields to your code:

C#

   Random intRand = new Random();
   List<Point> lstSol = new List<Point>();

   clsGame cGame = new clsGame();

VB.NET

   Dim intRand As New Random
   Dim lstSol As New List(Of Point)

   Dim cGame As New clsGame

We create a new Random object, a list object to hold the solution, and a new game object. Add the Load and Paint events:

C#

   private void Form1_Load(object sender, EventArgs e)
   {
      cboSize.SelectedIndex = 0;
   }

   private void Form1_Paint(object sender, PaintEventArgs e)
   {
      e.Graphics.DrawRectangle(Pens.Black, Maze1.Bounds);

   }

VB.NET

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

      cboSize.SelectedIndex = 0

   End Sub

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

      e.Graphics.DrawRectangle(Pens.Black, Maze1.Bounds)

   End Sub

Nothing serious here. The combobox defaults to the first item in the list (which is Beginner) and the outer bounds for the game get drawn according to the Maze object’s size.

Add the SelectedIndexChanged event for the ComboBox.

C#

   private void cboSize_SelectedIndexChanged(object sender,
      EventArgs e)
   {
      int sel = cboSize.SelectedIndex;

      if (sel == -1)
         return;
      Maze1.ShowSolution = false;

      Maze1.Columns.Clear();

      int i = sel == 0 ? 30 : sel == 1 ? 40 : 50;
      int j = sel == 0 ? 22 : sel == 1 ? 16 : 13;

      for (int c = 0; c <= i - 1; c++)
      {
         Maze1.Columns.Add(new DataGridViewTextBoxColumn()
            { ReadOnly = true, Width = j });
         Maze1.Rows.Add();
         Maze1.Rows[Maze1.Rows.Count - 1].Height = j;
      }

      Maze1.Size = new Size(i * j + 1, i * j + 1);
      Maze1.ShowCellToolTips = false;
      Maze1.DefaultCellStyle.SelectionBackColor =
         Color.FromArgb(175, 255, 60);

      this.SetClientSizeCore(Maze1.Width + 24, Maze1.Bottom + 50);

      btnNew.PerformClick();
      Maze1.Select();

      Maze1.Refresh();
      this.Refresh();
      chkSolve.Checked = false;
   }

VB.NET

   Private Sub cboSize_SelectedIndexChanged(sender As Object, _
         e As EventArgs) Handles cboSize.SelectedIndexChanged

      Dim sel As Integer = cboSize.SelectedIndex

      If sel = -1 Then Return
      Maze1.ShowSolution = False

      Maze1.Columns.Clear()

      Dim i As Integer = If(sel = 0, 30, If(sel = 1, 40, 50))
      Dim j As Integer = If(sel = 0, 22, If(sel = 1, 16, 13))

      For c As Integer = 0 To i - 1
         Maze1.Columns.Add(New DataGridViewTextBoxColumn With _
            {.ReadOnly = True, .Width = j})
         Maze1.Rows.Add()
         Maze1.Rows(Maze1.Rows.Count - 1).Height = j
      Next

      Maze1.Size = New Size(i * j + 1, i * j + 1)
      Maze1.ShowCellToolTips = False
      Maze1.DefaultCellStyle.SelectionBackColor = _
         Color.FromArgb(175, 255, 60)

      Me.SetClientSizeCore(Maze1.Width + 24, Maze1.Bottom + 50)

      btnNew.PerformClick()
      Maze1.Select()

      Maze1.Refresh()
      Me.Refresh()
      chkSolve.Checked = False
   End Sub

This code resizes the Maze object’s contents to adapt to the level of difficulty. The more advanced the level of the game, the more complicated and cluttered the screen becomes.

Add the New button’s code.

C#

   private void btnNew_Click(object sender, EventArgs e)
   {
      Maze1.ShowSolution = false;

      Maze1.Rows[0].Cells[clsGrid.ptEnd.X].Style.BackColor =
         Color.White;

      cGame.Generate(Maze1.Columns.Count, intRand);

      clsGrid.ptEnd = new Point(intRand.Next(0,
         Maze1.Rows.Count), 0);
      clsGrid.Cells[clsGrid.ptEnd.X][0].blnNorth = false;

      Maze1.Rows[0].Cells[clsGrid.ptEnd.X].Style.BackColor =
         Color.Green;
      Maze1.CurrentCell = Maze1.Rows[Maze1.Rows.Count - 1]
         .Cells[clsGrid.ptStart.X];
      chkSolve.Checked = false;
      Maze1.Refresh();

      bool[,] blnPrev = new bool[Maze1.Columns.Count - 1 + 1,
         Maze1.Rows.Count - 1 + 1];

      lstSol = new List<Point>();

      if (!cGame.Solve(Maze1.Columns.Count, clsGrid.ptStart.X,
            Maze1.Rows.Count - 1, blnPrev, lstSol))
         btnNew.PerformClick();

      Maze1.Select();
   }

VB.NET

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

      Maze1.ShowSolution = False

      Maze1.Rows(0).Cells(clsGrid.ptEnd.X).Style.BackColor = _
         Color.White

      cGame.Generate(Maze1.Columns.Count, intRand)

      clsGrid.ptEnd = New Point(intRand.Next(0, _
         Maze1.Rows.Count), 0)]
      clsGrid.Cells(clsGrid.ptEnd.X)(0).blnNorth = False

      Maze1.Rows(0).Cells(clsGrid.ptEnd.X).Style.BackColor = _
         Color.Green
      Maze1.CurrentCell = Maze1.Rows(Maze1.Rows.Count - 1) _
         .Cells(clsGrid.ptStart.X)
      chkSolve.Checked = False
      Maze1.Refresh()

      Dim blnPrev(Maze1.Columns.Count - 1, Maze1.Rows.Count - 1) _
         As Boolean

      lstSol = New List(Of Point)

      If Not cGame.Solve(Maze1.Columns.Count, clsGrid.ptStart.X, _
            Maze1.Rows.Count - 1, blnPrev, lstSol) Then
         btnNew.PerformClick()
      End If

      Maze1.Select()

   End Sub

This defaults all the objects on the screen. It provides a starting point as well as an ending point, and initializes all the objects to be used during game play.

Create the grid by adding the following code to the Maze object’s Paint event.

C#

   private void Maze1_Paint(object sender, PaintEventArgs e)
   {
      if (clsGrid.Cells == null)
         return;

      int sel = cboSize.SelectedIndex;
      if (sel == -1)
         return;

      int i = sel == 0 ? 30 : sel == 1 ? 40 : 50;
      int j = sel == 0 ? 22 : sel == 1 ? 16 : 13;

      for (int row = 0; row <= i - 1; row++)
      {
         for (int col = 0; col <= i - 1; col++)
         {
            if (clsGrid.Cells[col][row].blnNorth)
               e.Graphics.DrawLine(new Pen(Color.Black,
                  row == 0 ? 4 : 2), j * col, j * row,
                  j * (col + 1), j * row);
            if (clsGrid.Cells[col][row].blnSouth)
               e.Graphics.DrawLine(new Pen(Color.Black, 2),
                  j * col, j * (row + 1), j * (col + 1),
                  j * (row + 1));
            if (clsGrid.Cells[col][row].blnWest)
               e.Graphics.DrawLine(new Pen(Color.Black,
                  col == 0 ? 4 : 2), j * col, j * row,
                  j * col, j * (row + 1));
            if (clsGrid.Cells[col][row].blnEast)
               e.Graphics.DrawLine(new Pen(Color.Black, 2),
                  j * (col + 1), j * row, j * (col + 1),
                  j * (row + 1));
         }
      }
   }

VB.NET

   Private Sub Maze1_Paint(sender As Object, e As PaintEventArgs) _
         Handles Maze1.Paint

      If clsGrid.Cells Is Nothing Then Return

      Dim sel As Integer = cboSize.SelectedIndex
      If sel = -1 Then Return

      Dim i As Integer = If(sel = 0, 30, If(sel = 1, 40, 50))
      Dim j As Integer = If(sel = 0, 22, If(sel = 1, 16, 13))

      For row As Integer = 0 To i - 1
         For col As Integer = 0 To i - 1
            If clsGrid.Cells(col)(row).blnNorth Then
               e.Graphics.DrawLine(New Pen(Color.Black, _
                  If(row = 0, 4, 2)), j * col, j * row, _
                  j * (col + 1), j * row)
            End If
            If clsGrid.Cells(col)(row).blnSouth Then
               e.Graphics.DrawLine(New Pen(Color.Black, 2), _
                  j * col, j * (row + 1), j * (col + 1), _
                  j * (row + 1))
            End If
            If clsGrid.Cells(col)(row).blnWest Then
               e.Graphics.DrawLine(New Pen(Color.Black, _
                  If(col = 0, 4, 2)), j * col, j * row, _
                  j * col, j * (row + 1))
            End If
            If clsGrid.Cells(col)(row).blnEast Then
               e.Graphics.DrawLine(New Pen(Color.Black, 2), _
                  j * (col + 1), j * row, j * (col + 1), _
                  j * (row + 1))
            End If
         Next
      Next

   End Sub

Conclusion

Obviously, this project can be taken much, much further, but this is a good place to stop, because the inner workings and logic are complete. I hope that you have enjoyed this little series. Until next time, happy coding!

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