Page 1 of 1

Guessing Game (1 Game, 3 GUIs) Rate Topic: -----

#1 AdamSpeight2008  Icon User is offline

  • MrCupOfT
  • member icon


Reputation: 2271
  • View blog
  • Posts: 9,499
  • Joined: 29-May 08

Posted 29 March 2012 - 08:58 PM

Guessing Game (1 Game, 3 GUIS)

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: Attached File  Tutorial_GG.zip (43.03K)
Number of downloads: 697




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


Is This A Good Question/Topic? 2
  • +

Replies To: Guessing Game (1 Game, 3 GUIs)

#2 m_wylie85  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 96
  • View blog
  • Posts: 899
  • Joined: 15-October 10

Posted 30 March 2012 - 02:34 AM

HI Adam i was wonder what : is used for in the code below, as i have never seen this being used before:

 _LB = UB : _UB = LB  

Was This Post Helpful? 0
  • +
  • -

#3 AdamSpeight2008  Icon User is offline

  • MrCupOfT
  • member icon


Reputation: 2271
  • View blog
  • Posts: 9,499
  • Joined: 29-May 08

Posted 30 March 2012 - 02:39 AM

Statement separator (MSDN Documentation)
Was This Post Helpful? 0
  • +
  • -

#4 The Architect 2.0  Icon User is offline

  • D.I.C Regular

Reputation: 37
  • View blog
  • Posts: 351
  • Joined: 22-May 08

Posted 30 March 2012 - 03:59 AM

well, this example is trivial for obvious reasons. So i'll try to expand the topic to more conventionally sized projects.


What are your thoughts on PCL? I've never done multi-platform libraries before, so I'm not familiar with #IF PLATFORM pains.

While it feels like an intelli-sense plugin; I imagine everyone would begin to use it for their new libraries. At the very least, it seems like a great way to implement continous client using Azure(is that microsoft's goal in the first place? - encouraging azure usage?)
Was This Post Helpful? 0
  • +
  • -

#5 AdamSpeight2008  Icon User is offline

  • MrCupOfT
  • member icon


Reputation: 2271
  • View blog
  • Posts: 9,499
  • Joined: 29-May 08

Posted 30 March 2012 - 05:06 AM

The Architect 2.0: Of course it trivial example because it is a tutorial which demonstrates how simple it is to separate (or decouple) the Business Logic (or this case Game Logic) from the GUI. Choose too complex of an example and it'll frighten novices, each part is about 50 LoC (or a screen worth of code). Not too much to handle and study.
Was This Post Helpful? 0
  • +
  • -

#6 m_wylie85  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 96
  • View blog
  • Posts: 899
  • Joined: 15-October 10

Posted 30 March 2012 - 05:32 AM

Thanks adam
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1