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!