Refactor code to make Game its own Class to split from UI dedicated functions.

remotes/origin/master
CrystalMoogle 2023-07-16 15:13:43 +01:00
parent 1295bdbc09
commit 6880589562
8 changed files with 311 additions and 298 deletions

View File

@ -1,294 +0,0 @@
Public Class Form1
Inherits Form
Dim player As New Player()
Dim dealer As New Dealer()
Dim deck As New List(Of String)
Dim gameRunning As Boolean = True
Private Sub StartGame_Click(sender As Object, e As EventArgs) Handles StartGame.Click
PlayGame()
End Sub
Private Sub HitButton_Click(sender As Object, e As EventArgs) Handles HitButton.Click
If gameRunning And player.hand.Count < 5 And player.ingame Then
DealCard(player)
CheckPlayer(player)
End If
End Sub
Private Sub StandButton_Click(sender As Object, e As EventArgs) Handles StandButton.Click
If gameRunning And player.ingame Then
player.ingame = False
DealerTurn()
End If
End Sub
Private Sub ResetCards()
Dim pictureBoxes() As PictureBox = {PlayerCard1, PlayerCard2, PlayerCard3, PlayerCard4, PlayerCard5, PlayerCard6, PlayerCard7, PlayerCard8, PlayerCard9, PlayerCard10}
For Each box In pictureBoxes
box.Image = Nothing
Next
End Sub
Sub PlayGame()
InitGame()
End Sub
Sub InitGame()
ResetCards()
WinMessage.ResetText()
HitButton.Enabled = True
StandButton.Enabled = True
StartGame.Enabled = False
gameRunning = True
player.Start()
dealer.Start()
CreateDeck()
DealCard(player)
DealCard(dealer, isDealer:=True)
DealCard(player)
DealCard(dealer, isDealer:=True, hide:=True)
GetTotal(dealer)
CheckPlayer(dealer, True)
CheckPlayer(player)
End Sub
Sub CreateDeck()
deck.Clear()
Dim nums As String() = {"A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"}
Dim suits As String() = {"Hearts", "Diamonds", "Spades", "Clubs"}
For Each s As String In suits
For Each n As String In nums
deck.Add(n + " of " + s)
Next
Next
Shuffle(deck)
End Sub
Sub Shuffle(deck)
Dim max As Integer = deck.Count - 1
Dim random As New Random()
For x As Integer = 0 To max
Dim rand As Integer = random.Next(0, max)
Dim temp As String = deck(x)
deck(x) = deck(rand)
deck(rand) = temp
Next
End Sub
Sub DealCard(player, Optional suppress = False, Optional isDealer = False, Optional hide = False)
Dim card = deck(0)
player.hand.Add(card)
deck.RemoveAt(0)
GetTotal(player, hide)
Dim cardNumber As String = If(isDealer, (player.hand.count + 5).ToString(), player.hand.count)
Dim pictureBox As PictureBox
Try
pictureBox = CType(Me.Controls.Find("PlayerCard" + cardNumber, True).First(), PictureBox)
If hide Then
pictureBox.Image = My.Resources.blue
player.hidden = card
Else
pictureBox.Image = GetCardImage(card)
End If
SetTotalLabels()
Catch ex As Exception
WinMessage.Text = "Error: " + ex.Message
EndGame()
End Try
End Sub
Sub GetTotal(player, Optional hide = False)
If hide Then
Exit Sub
End If
Dim cards As List(Of String) = player.hand
If cards.Count = 0 Then
player.total = 0
Return
End If
Dim t As Integer = 0
Dim a As Integer = 0
For Each x As String In cards
Dim card As String = x
Dim num As String = card.Split(" "c)(0)
If num = "K" Or num = "Q" Or num = "J" Then
num = 10
End If
If num = "A" Then
num = 11
a += 1
End If
num = Integer.Parse(num)
t += num
Next
While (a > 0 And t > 21)
a -= 1
t = t - 10
End While
player.total = t
End Sub
Sub SetTotalLabels()
Dim dealerLabelTotal As String = DealerTotal.Text.Split(": ")(0)
Dim playerLabelTotal As String = PlayerTotal.Text.Split(": ")(0)
DealerTotal.Text = dealerLabelTotal + ": " + dealer.total.ToString()
PlayerTotal.Text = playerLabelTotal + ": " + player.total.ToString()
End Sub
Sub CheckPlayer(playerToCheck, Optional peek = False)
If Not peek Then
If playerToCheck.total = 21 And playerToCheck.hand.count = 2 Then
playerToCheck.winType = WinCondition.Blackjack
playerToCheck.ingame = False
dealer.ingame = False
DealerTurn()
ElseIf playerToCheck.total > 21 Then
playerToCheck.winType = WinCondition.Bust
playerToCheck.ingame = False
DealerTurn()
ElseIf playerToCheck.total < 22 And playerToCheck.hand.count = 5 Then
playerToCheck.winType = WinCondition.FiveCard
playerToCheck.ingame = False
dealer.ingame = False
DealerTurn()
End If
If playerToCheck.total = 21 Then
playerToCheck.ingame = False
DealerTurn()
End If
Else
If playerToCheck.total = 21 And playerToCheck.hand.count = 2 Then
playerToCheck.winType = WinCondition.Blackjack
playerToCheck.ingame = False
player.ingame = False
DealerTurn()
End If
End If
End Sub
Sub DealerTurn()
PlayerCard7.Image = GetCardImage(dealer.hidden)
GetTotal(dealer)
SetTotalLabels()
If player.winType = WinCondition.Bust Then
CheckGame()
Exit Sub
End If
If dealer.ingame And dealer.hand.Count < 5 Then
If dealer.total = 21 And dealer.hand.Count = 2 Then
dealer.winType = WinCondition.Blackjack
dealer.ingame = False
ElseIf dealer.total > 21 Then
dealer.winType = WinCondition.Bust
player.ingame = False
ElseIf dealer.total < dealer.limit Then
DealCard(dealer, isDealer:=True)
DealerTurn()
Else
dealer.winType = WinCondition.NormalWin
End If
End If
CheckGame()
End Sub
Sub CheckGame()
WinMessage.Text = GetResults()
EndGame()
End Sub
Sub EndGame()
HitButton.Enabled = False
StandButton.Enabled = False
StartGame.Enabled = True
End Sub
Function GetResults()
If dealer.winType = WinCondition.Blackjack Then
If player.winType = WinCondition.Blackjack Then
PrintCurrentGame()
Return "Player ties with Blackjack!"
Else
PrintCurrentGame()
Return "Dealer wins with Blackjack!"
End If
End If
If player.winType = WinCondition.Blackjack Then
PrintCurrentGame()
Return "Player wins with Blackjack!"
End If
If player.winType = WinCondition.FiveCard Then
PrintCurrentGame()
Return "Player wins with Five Card Charlie!"
End If
If player.winType = WinCondition.Bust Then
PrintCurrentGame()
Return "Player busts!"
End If
If dealer.winType = WinCondition.Bust Then
PrintCurrentGame()
Return "Dealer busts!"
End If
If player.total > dealer.total Then
PrintCurrentGame()
Return "Player wins with total of " + player.total.ToString() + "!"
End If
If player.total = dealer.total Then
PrintCurrentGame()
Return "Tie!"
End If
If player.total < dealer.total Then
PrintCurrentGame()
Return "Dealer wins with total of " + dealer.total.ToString() + "!"
End If
PrintCurrentGame()
Return "error"
End Function
Function GetCardImage(card) As Image
Dim num As String = card.split(" ")(0)
Dim suit As String = card.split(" ")(2)
Select Case num
Case "K"
num = "king"
Case "Q"
num = "queen"
Case "J"
num = "jack"
Case "A"
num = "ace"
End Select
Dim img As String = suit + "_" + num
Return My.Resources.ResourceManager.GetObject(img.ToLower())
End Function
Sub PrintCurrentGame()
Console.WriteLine("Dealer Hand: " + String.Join(", ", dealer.hand) + " Total: " + dealer.total.ToString())
Console.WriteLine("Player Hand: " + String.Join(", ", player.hand) + " Total: " + player.total.ToString())
End Sub
End Class
Public Class Player
Private _winCondition As WinCondition
Public Property hand As New List(Of String)
Public Property total As Integer
Public Property ingame As Boolean
Public Property winType
Get
Return _winCondition
End Get
Set
_winCondition = Value
End Set
End Property
Sub Start()
hand.Clear()
total = 0
ingame = True
winType = WinCondition.NormalWin
End Sub
End Class
Public Class Dealer
Inherits Player
Public Property limit As Integer = 17
Public Property hidden As String
End Class
Enum WinCondition
Bust
NormalWin
FiveCard
Blackjack
End Enum

View File

@ -1,5 +1,5 @@
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()>
Partial Class Form1
Partial Class GameWindow
Inherits System.Windows.Forms.Form
'Form overrides dispose to clean up the component list.
@ -230,7 +230,7 @@ Partial Class Form1
WinMessage.Size = New Size(0, 30)
WinMessage.TabIndex = 15
'
' Form1
' GameWindow
'
AutoScaleMode = AutoScaleMode.Inherit
ClientSize = New Size(1264, 681)
@ -251,7 +251,7 @@ Partial Class Form1
Controls.Add(StandButton)
Controls.Add(HitButton)
MinimumSize = New Size(1280, 720)
Name = "Form1"
Name = "GameWindow"
StartPosition = FormStartPosition.CenterScreen
Text = "Blackjack"
CType(PlayerCard1, ComponentModel.ISupportInitialize).EndInit()

View File

@ -0,0 +1,58 @@
Public Class GameWindow
Private WithEvents game As Game
Private Sub StartGame_Click(sender As Object, e As EventArgs) Handles StartGame.Click
game = New Game()
game.Start()
End Sub
Private Sub HitButton_Click(sender As Object, e As EventArgs) Handles HitButton.Click
game.Hit()
End Sub
Private Sub StandButton_Click(sender As Object, e As EventArgs) Handles StandButton.Click
game.Stand()
End Sub
Private Sub OnResetUI() Handles game.ResetUI
Dim pictureBoxes() As PictureBox = {PlayerCard1, PlayerCard2, PlayerCard3, PlayerCard4, PlayerCard5, PlayerCard6, PlayerCard7, PlayerCard8, PlayerCard9, PlayerCard10}
For Each box In pictureBoxes
box.Image = Nothing
Next
WinMessage.ResetText()
HitButton.Enabled = True
StandButton.Enabled = True
StartGame.Enabled = False
End Sub
Private Sub OnCardDealt(card As String, cardNumber As String, hide As Boolean) Handles game.CardDealt
Dim pictureBox As PictureBox
Debug.Print(cardNumber)
Try
pictureBox = CType(Me.Controls.Find("PlayerCard" + cardNumber, True).First(), PictureBox)
If hide Then
pictureBox.Image = My.Resources.blue
Else
pictureBox.Image = Utilities.GetCardImage(card)
End If
Catch ex As Exception
EndGame("Error: " + ex.Message)
End Try
End Sub
Private Sub SetTotalLabels(playerTotalAmount, dealerTotalAmount) Handles game.SetTotalLabels
Dim dealerLabelTotal As String = DealerTotal.Text.Split(": ")(0)
Dim playerLabelTotal As String = PlayerTotal.Text.Split(": ")(0)
DealerTotal.Text = dealerLabelTotal + ": " + dealerTotalAmount.ToString()
PlayerTotal.Text = playerLabelTotal + ": " + playerTotalAmount.ToString()
End Sub
Private Sub ShowDealerCard(card) Handles game.ShowDealerCard
PlayerCard7.Image = Utilities.GetCardImage(card)
End Sub
Private Sub EndGame(message) Handles game.EndGame
WinMessage.Text = message
HitButton.Enabled = False
StandButton.Enabled = False
StartGame.Enabled = True
End Sub
End Class

View File

@ -31,7 +31,7 @@ Namespace My
<Global.System.Diagnostics.DebuggerStepThroughAttribute()>
Protected Overrides Sub OnCreateMainForm()
Me.MainForm = Form1
Me.MainForm = GameWindow
End Sub
End Class
End Namespace

View File

@ -0,0 +1,30 @@
Public Class Utilities
Public Shared Function Shuffle(list)
Dim max As Integer = list.Count - 1
Dim random As New Random()
For x As Integer = 0 To max
Dim rand As Integer = random.Next(0, max)
Dim temp As String = list(x)
list(x) = list(rand)
list(rand) = temp
Next
Return list
End Function
Public Shared Function GetCardImage(card) As Image
Dim num As String = card.split(" ")(0)
Dim suit As String = card.split(" ")(2)
Select Case num
Case "K"
num = "king"
Case "Q"
num = "queen"
Case "J"
num = "jack"
Case "A"
num = "ace"
End Select
Dim img As String = suit + "_" + num
Return My.Resources.ResourceManager.GetObject(img.ToLower())
End Function
End Class

View File

@ -0,0 +1,191 @@
Public Class Game
Public Event ResetUI()
Public Event CardDealt(card, cardNumber, hide)
Public Event SetTotalLabels(playerTotal, dealerTotal)
Public Event ShowDealerCard(card)
Public Event EndGame(winMessage)
Private player As Player
Private dealer As Dealer
Private deck As New List(Of String)
Public Sub Start()
Init()
player.Start()
dealer.Start()
DealCard(player)
DealCard(dealer, isDealer:=True)
DealCard(player)
DealCard(dealer, isDealer:=True, hide:=True)
CheckPlayer(player)
CheckPlayer(dealer, True)
End Sub
Sub Init()
player = New Player()
dealer = New Dealer()
deck = CreateDeck()
RaiseEvent ResetUI()
End Sub
Sub DealCard(playerDealt, Optional isDealer = False, Optional hide = False)
Dim card As String = deck(0)
playerDealt.hand.Add(card)
deck.RemoveAt(0)
GetTotal(playerDealt, hide)
If hide Then
playerDealt.hidden = card
End If
Dim cardNumber As String = If(isDealer, (playerDealt.hand.Count + 5).ToString(), playerDealt.hand.Count)
RaiseEvent CardDealt(card, cardNumber, hide)
RaiseEvent SetTotalLabels(player.total, dealer.total)
End Sub
Sub GetTotal(playerToCheck, Optional hide = False)
If hide Then
Exit Sub
End If
Dim cards As List(Of String) = playerToCheck.hand
If cards.Count = 0 Then
playerToCheck.total = 0
Return
End If
Dim total As Integer = 0
Dim aceTotal As Integer = 0
For Each card As String In cards
Dim num As String = card.Split(" "c)(0)
If num = "K" Or num = "Q" Or num = "J" Then
num = 10
End If
If num = "A" Then
num = 11
aceTotal += 1
End If
num = Integer.Parse(num)
total += num
Next
While (aceTotal > 0 And total > 21)
aceTotal -= 1
total -= 10
End While
playerToCheck.total = total
End Sub
Sub CheckPlayer(playerToCheck, Optional peek = False)
If playerToCheck.total = 21 And playerToCheck.hand.count = 2 And peek Then
playerToCheck.winType = WinCondition.Blackjack
playerToCheck.ingame = False
player.ingame = False
DealerTurn()
Exit Sub
End If
If playerToCheck.total = 21 And playerToCheck.hand.count = 2 Then
playerToCheck.winType = WinCondition.Blackjack
playerToCheck.ingame = False
dealer.ingame = False
DealerTurn()
ElseIf playerToCheck.total > 21 Then
playerToCheck.winType = WinCondition.Bust
playerToCheck.ingame = False
DealerTurn()
ElseIf playerToCheck.total < 22 And playerToCheck.hand.count = 5 Then
playerToCheck.winType = WinCondition.FiveCard
playerToCheck.ingame = False
dealer.ingame = False
DealerTurn()
End If
If playerToCheck.total = 21 Then
playerToCheck.ingame = False
DealerTurn()
End If
End Sub
Sub DealerTurn()
GetTotal(dealer)
RaiseEvent SetTotalLabels(player.total, dealer.total)
RaiseEvent ShowDealerCard(dealer.hidden)
If player.winType = WinCondition.Bust Then
CheckGame()
Exit Sub
End If
If dealer.ingame And dealer.hand.Count < 5 Then
If dealer.total = 21 And dealer.hand.Count = 2 Then
dealer.winType = WinCondition.Blackjack
dealer.ingame = False
ElseIf dealer.total > 21 Then
dealer.winType = WinCondition.Bust
player.ingame = False
ElseIf dealer.total < dealer.limit Then
DealCard(dealer, isDealer:=True)
DealerTurn()
Else
dealer.winType = WinCondition.NormalWin
End If
End If
CheckGame()
End Sub
Sub Hit()
If player.hand.Count < 5 And player.ingame Then
DealCard(player)
CheckPlayer(player)
End If
End Sub
Sub Stand()
If player.ingame Then
player.ingame = False
DealerTurn()
End If
End Sub
Sub CheckGame()
Dim winMessage As String = GetResults()
RaiseEvent EndGame(winMessage)
End Sub
Function GetResults()
If dealer.winType = WinCondition.Blackjack Then
If player.winType = WinCondition.Blackjack Then
Return "Player ties with Blackjack!"
Else
Return "Dealer wins with Blackjack!"
End If
End If
If player.winType = WinCondition.Blackjack Then
Return "Player wins with Blackjack!"
End If
If player.winType = WinCondition.FiveCard Then
Return "Player wins with Five Card Charlie!"
End If
If player.winType = WinCondition.Bust Then
Return "Player busts!"
End If
If dealer.winType = WinCondition.Bust Then
Return "Dealer busts!"
End If
If player.total > dealer.total Then
Return "Player wins with total of " + player.total.ToString() + "!"
End If
If player.total = dealer.total Then
Return "Tie!"
End If
If player.total < dealer.total Then
Return "Dealer wins with total of " + dealer.total.ToString() + "!"
End If
Return "error"
End Function
Function CreateDeck()
deck.Clear()
Dim nums As String() = {"A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"}
Dim suits As String() = {"Hearts", "Diamonds", "Spades", "Clubs"}
For Each s As String In suits
For Each n As String In nums
deck.Add(n + " of " + s)
Next
Next
Return Utilities.Shuffle(deck)
End Function
End Class
Public Enum WinCondition
Bust
NormalWin
FiveCard
Blackjack
End Enum

View File

@ -0,0 +1,28 @@
Public Class Player
Private _winCondition As WinCondition
Public Property hand As New List(Of String)
Public Property total As Integer
Public Property ingame As Boolean
Public Property winType
Get
Return _winCondition
End Get
Set
_winCondition = Value
End Set
End Property
Sub Start()
hand.Clear()
total = 0
ingame = True
winType = WinCondition.NormalWin
End Sub
End Class
Public Class Dealer
Inherits Player
Public Property limit As Integer = 17
Public Property hidden As String
End Class