The Guessing Game is really simple.
Computer picks a random number (within some range) and user attempts to guess that number.
If the number matches what the computer picked then the Player Wins
If the number is higher than the number the computer replies with "Too High"
If the number is lower than the number the computer replies with "Too Low"
This continues until the number is guessed or player runs out guesses
Let implement it not only once but three times.
- Console Application
- WinForms Applications
- WPF Application
That sounds like a lot a work, but if you think about it all that changes is the Graphic User Interface (GUI).
So let's create the core of the game.
Public Class GuessingGame #Region "Private Member Variables" Private _Rnd = New System.Random Private Const DefaultNoGuess = 6 Private GuessesToBeginWith , Guesses, Answer, _LB, _UB As Integer Private _Done As Boolean = False #End Region
We've declared all of the variables that we'll be using.
Now let do the properties.
#Region "Properties"
Public ReadOnly Property Done() As Boolean
Get
Return _Done
End Get
End Property
Public ReadOnly Property LowerBounds As Integer
Get
Return _LB
End Get
End Property
Public ReadOnly Property UpperBounds As Integer
Get
Return _UB
End Get
End Property
Public ReadOnly Property GuessesLeft As Integer
Get
Return Guesses
End Get
End Property
#End Region
So on the constructor.
#Region "Constructor(s)"
Public Sub New(LB As Integer, UB As Integer, Optional NoGuesses As Integer = DefaultNoGuess)
If LB > UB Then
_LB = UB : _UB = LB
Else
_UB = UB : _LB = LB
End If
GuessesToBeginWith = If(NoGuesses <= 0, DefaultNoGuess, NoGuesses)
End Sub
#End Region
The key part of the design.
It is the key part as this decouples the game code from the GUI.
#Region "Public Events" Public Event TooHigh() Public Event TooLow() Public Event NumberGuessed() Public Event GameOver(Answer As Integer) Public Event GameAlreadyFinished() #End Region
The GUI responds to these events.
The Game Logic
So we begin by enable use to start a new game.
#Region "Public Methods"
Public Sub StartNewGame()
Answer = _Rnd.Next(_LB, _UB)
Guesses = GuessesToBeginWith
_Done = False
End Sub
As can see the core of the Guessing Game control logic is very small.
In the region of 13 Lines of Code.
Public Sub PlayGuess(Number As Integer)
If Done Then
RaiseEvent GameAlreadyFinished()
Else
Guesses -= 1
Select Case True
Case Number = Answer : RaiseEvent NumberGuessed()
Case Number < Answer : RaiseEvent TooLow()
Case Number > Answer : RaiseEvent TooHigh()
End Select
If Guesses = 0 Then RaiseEvent GameOver(Answer)
End If
End Sub
#End Region
Using the Events Internally
There's nothing stopping us from utilizing the events the game logic raises. These will be the first ones called, when the event happens.
Private Sub GuessingGameController_GameOver(Answer As Integer) Handles Me.GameOver
_Done = True
End Sub
Private Sub GuessingGameController_NumberGuessed() Handles Me.NumberGuessed
_Done = True
End Sub
End Class
So the Guessing Game is around 75 Lines of Code.
We build this has a Class Library and be I'll name mine GuessingGame_Core
Console Application
Add a reference to the GuessingGame_Core class library.
Imports GuessingGame_Core Module Module1 Dim WithEvents gg As GuessingGame
The WithEvents will allow use to the Handles langauge feature
Sub Main()
gg = New GuessingGame(0, 100)
gg.StartNewGame()
Do
Dim gs As String
Dim gn As Integer
Console.WriteLine("Number to guess is between {0} and {1}", gg.LowerBounds, gg.UpperBounds)
Do
Console.Write("Your Guess: ")
gs = Console.ReadLine()
Console.WriteLine()
Loop Until Integer.TryParse(gs, gn)
gg.PlayGuess(gn)
Loop Until gg.Done
End Sub
Private Sub gg_GameOver(Answer As Integer) Handles gg.GameOver
Console.WriteLine("You Lost, Number was {0}", Answer)
End Sub
Private Sub gg_NumberGuessed() Handles gg.NumberGuessed
Console.WriteLine("You Won")
End Sub
Private Sub gg_TooHigh() Handles gg.TooHigh
Console.WriteLine("Too High")
End Sub
Private Sub gg_TooLow() Handles gg.TooLow
Console.WriteLine("Too Low")
End Sub
End Module
So we now have a simple Guessing Game in about 30 Lines of Code.
WinForms Application
Imports GuessingGame_Core
Public Class GuessGameForm
Dim WithEvents GuessingGame As GuessingGame
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
GuessingGame = New GuessingGame(0, 100, 6)
GuessingGame.StartNewGame()
Me.YourGuessNumber.Minimum = GuessingGame.LowerBounds
Me.YourGuessNumber.Value = GuessingGame.LowerBounds
Me.YourGuessNumber.Maximum = GuessingGame.UpperBounds
Me.GuessesLeft.Text = GuessingGame.GuessesLeft
End Sub
Private Sub gg_GameOver(Answer As Integer) Handles GuessingGame.GameOver
Response.Text = String.Format("You Lost, Number was {0}", Answer)
End Sub
Private Sub gg_NumberGuessed() Handles GuessingGame.NumberGuessed
Response.Text = "You Won"
End Sub
Private Sub gg_TooHigh() Handles GuessingGame.TooHigh
Response.Text = "Too High"
GuessesLeft.Text = GuessingGame.GuessesLeft
End Sub
Private Sub gg_TooLow() Handles GuessingGame.TooLow
Response.Text = "Too Low"
GuessesLeft.Text = GuessingGame.GuessesLeft
End Sub
Private Sub PlayGuessButton_Click(sender As System.Object, e As System.EventArgs) Handles PlayGuessButton.Click
GuessingGame.PlayGuess(Me.YourGuessNumber.Value)
End Sub
Private Sub NewGameButton_Click(sender As System.Object, e As System.EventArgs) Handles NewGameButton.Click
GuessingGame.StartNewGame()
GuessesLeft.Text = GuessingGame.GuessesLeft
Response.Text = ""
YourGuessNumber.Value = GuessingGame.LowerBounds
End Sub
Private Sub ExitButton_Click(sender As System.Object, e As System.EventArgs) Handles ExitButton.Click
Application.Exit()
End Sub
End Class
WPF Application
Imports GuessingGame_Core
Class MainWindow
Dim WithEvents GuessingGame As GuessingGame
Private Sub MainWindow_Loaded(sender As Object, e As System.Windows.RoutedEventArgs) Handles Me.Loaded
GuessingGame = New GuessingGame(0, 100, 6)
GuessingGame.StartNewGame()
Me.YourGuess.Minimum = GuessingGame.LowerBounds
Me.YourGuess.Value = GuessingGame.LowerBounds
Me.YourGuess.Maximum = GuessingGame.UpperBounds
Me.GuessesLeft.Content = GuessingGame.GuessesLeft
End Sub
Private Sub GuessButton_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles GuessButton.Click
GuessingGame.PlayGuess(CInt(Me.YourGuess.Value))
Me.GuessesLeft.Content = GuessingGame.GuessesLeft
End Sub
Private Sub NewGameButton_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles NewGameButton.Click
Me.GuessingGame.StartNewGame()
Me.Response.Content = ""
End Sub
Private Sub ExitButton_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles ExitButton.Click
My.Application.Shutdown()
End Sub
Private Sub GuessingGame_GameOver(Answer As Integer) Handles GuessingGame.GameOver
Response.Content = String.Format("You Lost, Number was {0}", Answer)
End Sub
Private Sub GuessingGame_NumberGuessed() Handles GuessingGame.NumberGuessed
Response.Content = "You Won"
End Sub
Private Sub GuessingGame_TooHigh() Handles GuessingGame.TooHigh
Response.Content = "Too High"
End Sub
Private Sub GuessingGame_TooLow() Handles GuessingGame.TooLow
Response.Content = "Too Low"
End Sub
Private Sub YourGuess_ValueChanged(sender As Object, e As System.Windows.RoutedPropertyChangedEventArgs(Of Double)) Handles YourGuess.ValueChanged
If Me.GuessValue IsNot Nothing Then Me.GuessValue.Content = CInt(e.NewValue)
End Sub
End Class
Downloads
Tutorial Project Download:
Tutorial_GG.zip (43.03K)
Number of downloads: 3725
Conclusion
We've written less than 200 LoC and implemented the Guessing Game under three different GUIs (Console, WinForms, WPF). This leads me to the conclusion that separating the Core Game Logic from the UI is beneficial not only in terms of Code Size but that code is simple to understand and code. This is because the intricacies and complication of the GUI are abstracted away.
Edit: Correcting WinForms code to actual WinForms that should be there.
Thanks go to lucky3 for spotting it.
This post has been edited by AdamSpeight2008: 19 August 2012 - 01:14 PM





MultiQuote




|