VB.Net - Perspective
Overview
This is an original Maths and Grammar quiz game. The aim of the game is to climb the board to the end square.
Youtube video - (If the embedded video doesn't appear, use this external link: https://youtu.be/J1RaU9vLXf4) - View
To play, you spin the number spinner by pressing the spin button. Each time you pass over a '?' square, you will be asked a question. There are three possible outcomes...
Possible outcomes
You can Pass
You decline answering the question. If you have remaining moves, you continue to climb the board. If not, you will be asked another question.
You answer correctly
Your remaining moves will be increased, and you continue to climb the board.
Remaining moves * 2 + 1
You answer incorrectly
You lose your remaining moves and you are sent back to the previous question square, or if there isn't a previous question square, you are sent back to the start.
The Grammar Question Form
The Grammar questions along with their multi-choice answers and their correct answers are stored in a My.Resources text file.
Public Class frmGrammar
''' <summary>
''' Used to stop questions being randomly repeated
''' </summary>
''' <remarks></remarks>
Private _used As List(Of Integer)
Public Property indicesUsed() As List(Of Integer)
Get
Return _used
End Get
Set ( ByVal value As List(Of Integer))
_used = value
End Set
End Property
''' <summary>
''' Constructor
''' </summary>
''' <param name="r"></param>
''' <param name="used"></param>
''' <remarks>Selects a random question and puts the multi-choice answers in labels</remarks>
Public Sub New(ByVal r As Random, ByVal used As List(Of Integer))
InitializeComponent()
Dim lines() As String = My.Resources.quiz.Split(New String() {Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries)
If used.Count = lines.Length Then
used.Clear()
End If
Dim i As Integer = r.Next(0, lines.Length)
While used.Contains(i)
i = r. Next (0, lines.Length)
End While
used.Add(i)
indicesUsed = used
Dim parts() As String = lines(i).Split(":"c)
Dim s1 As String = parts(0).Substring(0, parts(0).IndexOf("{"))
Dim s2 As String = parts(0).Substring(parts(0).IndexOf("}") + 1)
Dim s3 As String = parts(0).Substring(parts(0).IndexOf("{") + 1, parts(0).IndexOf("}") - parts(0).IndexOf("{") - 1)
Dim words() As String = s3.Split("|"c)
Label1.Text = s1 & "_____" & s2
Dim labels() As Label = {Label2, Label3, Label4, Label5}
For x As Integer = 0 To 3
If x <= words.GetUpperBound(0) Then
labels(x).Text = words(x)
Else
labels(x).Text = ""
labels(x).Visible = False
End If
Next
Dim w As Integer = Label6.Width + Label7.Width
For x As Integer = 0 To 3
If labels(x).Text <> "" Then
w += labels(x).Width + 6
End If
Next
w -= 6
Dim xp As Integer = (Me.ClientSize.Width - w) \ 2
Label6.Left = xp
labels(0).Left = Label6.Right
For x As Integer = 1 To 3
If labels(x).Text <> "" Then
labels(x).Left = labels(x - 1).Right + 6
Label7.Left = labels(x).Right
End If
Next
correctAnswer = CInt (parts(1))
'Stop
End Sub
Private correctAnswer As Integer
Private selectedAnswer As Integer
''' <summary>
''' btnPass
''' </summary>
''' <param name="sender"></param>
''' <param name="e"></param>
''' <remarks>Clicked when user declines question</remarks>
Private Sub btnPass_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPass.Click
Me .DialogResult = Windows.Forms.DialogResult.Cancel
End Sub
''' <summary>
''' btnSolve
''' </summary>
''' <param name="sender"></param>
''' <param name="e"></param>
''' <remarks>Form.DialogResult depends on whether the answer is correct</remarks>
Private Sub btnSolve_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSolve.Click
If selectedAnswer = correctAnswer Then
Label8.Text = "✔"
Label8.Refresh()
Threading.Thread.Sleep(500)
Me .DialogResult = Windows.Forms.DialogResult.Yes
Else
Label8.Text = "X"
Label8.Refresh()
Threading.Thread.Sleep(500)
Me .DialogResult = Windows.Forms.DialogResult.No
End If
End Sub
''' <summary>
''' Labels_Click
''' </summary>
''' <param name="sender"></param>
''' <param name="e"></param>
''' <remarks>Onclick the Label forecolor and fontsize changes.
''' This resets all of the other labels, so only one appears selected.
''' Adjust locations to centre multi-choice Labels in Form</remarks>
Private Sub Labels_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Label5.Click, Label4.Click, Label3.Click, Label2.Click
Dim labels() As Label = {Label2, Label3, Label4, Label5}
For x As Integer = 0 To 3
labels(x).ForeColor = Color.Silver
labels(x).Font = New Font(labels(x).Font.FontFamily, 10)
labels(x).Top = 109
Next
Dim i As Integer = Array.IndexOf(labels, sender)
selectedAnswer = i
labels(i).ForeColor = Color.SteelBlue
labels(i).Font = New Font(labels(i).Font.FontFamily, 14)
labels(i).Top = 125 - labels(i).Height + 3
Dim w As Integer = Label6.Width + Label7.Width
For x As Integer = 0 To 3
If labels(x).Text <> "" Then
w += labels(x).Width + 6
End If
Next
w -= 6
Dim xp As Integer = (Me.ClientSize.Width - w) \ 2
Label6.Left = xp
labels(0).Left = Label6.Right
For x As Integer = 1 To 3
If labels(x).Text <> "" Then
labels(x).Left = labels(x - 1).Right + 6
Label7.Left = labels(x).Right
End If
Next
btnSolve.Enabled = True
End Sub
End Class
The Maths Question Form
Public Class frmMaths
Private correctAnswer As Integer
Dim x As Integer
Dim dt As New DataTable
Dim operands(,) As String = {{"+", "-"}, {"/", "*"}}
''' <summary>
''' Constructor
''' </summary>
''' <param name="r"></param>
''' <remarks>Sets up NumericUpDown1.TextChanged
''' Formulates a random equation string with a hidden value
''' </remarks>
Public Sub New(ByVal r As Random)
InitializeComponent()
AddHandler DirectCast(NumericUpDown1.Controls(1), TextBox).TextChanged, AddressOf txtChanged
Dim i1 As Integer = r.Next(2, 11)
Dim i2 As Integer = r.Next(2, 11)
Dim i3 As Integer = r.Next(2, 11)
Do While i2 = i1
i2 = r. Next (1, 11)
Loop
Do While i3 = i1 Or i3 = i2
i3 = r. Next (1, 11)
Loop
Dim s1 As String = operands(0, r.Next(0, 2)) & " " & i1.ToString
Dim s2 As String = operands(1, r.Next(0, 2)) & " " & i2.ToString
Dim s3 As String = operands(0, r.Next(0, 2)) & " " & i3.ToString
x = r. Next (1, 101)
Dim s4 As String = String.Format("((({0} {1}) {2}) {3})", x, s1, s2, s3)
Do While CDec(dt.Compute(s4, Nothing)) Mod 1 <> 0
x = r. Next (1, 101)
s4 = String .Format( "((({0} {1}) {2}) {3})" , x, s1, s2, s3)
Loop
Label1.Text = String .Format( "x {0} {1} {2}" , s1, s2, s3) & " = " & CInt(dt.Compute(s4, Nothing)).ToString
correctAnswer = x
End Sub
''' <summary>
''' Pass Button
''' </summary>
''' <param name="sender"></param>
''' <param name="e"></param>
''' <remarks>Clicked if user declines the question</remarks>
Private Sub btnPass_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPass.Click
Me .DialogResult = Windows.Forms.DialogResult.Cancel
End Sub
''' <summary>
''' Solve Button
''' </summary>
''' <param name="sender"></param>
''' <param name="e"></param>
''' <remarks>Form.DialogResult depends on whether the answer is correct</remarks>
Private Sub btnSolve_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSolve.Click
If CInt(NumericUpDown1.Value) = correctAnswer Then
Label8.Text = "✔"
Label8.Refresh()
Threading.Thread.Sleep(500)
Me .DialogResult = Windows.Forms.DialogResult.Yes
Else
Label8.Text = "X"
Label8.Refresh()
Threading.Thread.Sleep(500)
Me .DialogResult = Windows.Forms.DialogResult.No
End If
End Sub
''' <summary>
''' NumericUpDown1.ValueChanged
''' </summary>
''' <param name="sender"></param>
''' <param name="e"></param>
''' <remarks>Enables/disable btnSolve depending if NumericUpDown1.Value > 0D</remarks>
Private Sub NumericUpDown1_ValueChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles NumericUpDown1.ValueChanged
btnSolve.Enabled = NumericUpDown1.Value > 0D
End Sub
''' <summary>
''' NumericUpDown1.TextChanged
''' </summary>
''' <param name="sender"></param>
''' <param name="e"></param>
''' <remarks>Enables/disable btnSolve depending if NumericUpDown1.Value > 0</remarks>
Private Sub txtChanged(ByVal sender As System.Object, ByVal e As System.EventArgs)
Dim tb As TextBox = DirectCast(sender, TextBox)
btnSolve.Enabled = Val(tb.Text) > 0
End Sub
''' <summary>
''' Details1.Resize
''' </summary>
''' <param name="sender"></param>
''' <param name="e"></param>
''' <remarks>Resizes Form when the dropdown calculator is shown/hidden</remarks>
Private Sub Details1_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles Details1.Resize
Me .Height = 205 + Details1.Height
End Sub
End Class
Conclusion
In VB.Net, a lot can be accomplished, while using only minimal controls, and effective coding. The Game 'board' in the main form of this game uses only one image, two Buttons, a PictureBox, and another (custom) PictureBox which has a circular region. All of the question forms also use minimal resources.
Download
MSDN Code Gallery version...
Download here...
Articles related to game programming
VB.Net - Vertex
VB.Net - WordSearch
VB.Net - MasterMind
VB.Net - OOP BlackJack
VB.Net - Numbers Game
VB.Net - HangMan
Console BlackJack - VB.Net | C#
TicTacToe - VB.Net | C#
OOP Conway's Game of Life - VB.Net | C#
OOP Sudoku - VB.Net | C#
OctoWords VB.Net | C#
OOP Buttons Guessing Game VB.Net | C#
OOP Tangram Shapes Game VB.Net | C#
VB.Net - Three-card Monte
VB.Net - Split Decisions
VB.Net - Pascal's Pyramid
VB.Net - Random Maze Games
(Office) Wordsearch Creator
VB.Net - Event Driven Programming - LockWords Game
C# - Crack the Lock
VB.Net - Totris