# Overview

This is a console game that I first wrote in VB 2013 and then re-wrote in C# 2013 as a learning exercise. Anyone who has ever played cards before has probably played BlackJack.
Blackjack, also known as twenty-one, is the most widely played casino banking game in the world. Blackjack is a comparing card game between a player and dealer.  Players compete against the dealer but not against any other players. It is played (in this version) with a deck of 52 cards. The object of the game is to beat the dealer, which can be done in a number of ways:
• Get 21 points on the player's first two cards (called a blackjack), without a dealer blackjack;
• Reach a final score higher than the dealer without exceeding 21; or
• Let the dealer draw additional cards until his or her hand exceeds 21.
The player is dealt an initial two-card hand and adds together the value of their cards. Face cards (kings, queens, and jacks) are counted as ten points. A player and the dealer can count his or her own ace as 1 point or 11 points. All other cards are counted as the numeric value shown on the card. After receiving their initial two cards, players have the option of getting a "hit" (twisting), which is taking an additional card, or not (sticking). In a given round, the player or the dealer wins by having a score of 21 or by having the highest score that is less than 21. Scoring higher than 21 (called "busting" or "going bust") results in a loss. A player may win by having any final score equal to or less than 21 if the dealer busts.

# The Code

First some Variables and a Structure, at Module level, to hold the deck of cards, the values of the cards, and the game statistics.
​There's also a Module level Random Object, which is used when shuffling the deck.

Dim deck() As String

Dim r As New Random
Private Structure value

Dim cardName As String

Dim cardValue As Integer

Public Sub New(ByVal cn As String, ByVal cv As Integer)

Me.cardName = cn

Me.cardValue = cv

End Sub

End Structure
Dim values As New List(Of value)
Dim gamesPlayed As Integer

Dim youWon As Integer

Dim dealerWon As Integer
Dim balance As Decimal = 100D
Dim bet As Decimal

In Sub Main, the suits Arrays are loaded, and also the values List. then the game loop begins...

Sub Main()
Dim hearts() As String = Enumerable.Range(2, 9).Select(Function(x) x.ToString & Chr(3)).ToArray

hearts = hearts.Concat(New String() {"J" & Chr(3), "Q" & Chr(3), "K" & Chr(3), "A" & Chr(3)}).ToArray
Dim diamonds() As String = Enumerable.Range(2, 9).Select(Function(x) x.ToString & Chr(4)).ToArray

diamonds = diamonds.Concat(New String() {"J" & Chr(4), "Q" & Chr(4), "K" & Chr(4), "A" & Chr(4)}).ToArray
Dim clubs() As String = Enumerable.Range(2, 9).Select(Function(x) x.ToString & Chr(5)).ToArray

clubs = clubs.Concat(New String() {"J" & Chr(5), "Q" & Chr(5), "K" & Chr(5), "A" & Chr(5)}).ToArray
Dim spades() As String = Enumerable.Range(2, 9).Select(Function(x) x.ToString & Chr(6)).ToArray

spades = spades.Concat(New String() {"J" & Chr(6), "Q" & Chr(6), "K" & Chr(6), "A" & Chr(6)}).ToArray

Dim playAgain As String
Do

playAgain = If(balance > 0, playAHand(), "n")
If playAgain.ToLower = "y" Then

shuffle()
Dim playersHand() As String = deal(2)

Dim dealersHand() As String = deal(2)

Dim dealerScore As Integer = dealersHand.Sum(Function(c) values.First(Function(v) If(Val(c) > 0, Val(c).ToString = v.cardName, c.StartsWith(v.cardName))).cardValue)

If dealerScore = 22 Then dealerScore = 12
Dim playerScore As Integer = playersHand.Sum(Function(c) values.First(Function(v) If(Val(c) > 0, Val(c).ToString = v.cardName, c.StartsWith(v.cardName))).cardValue)

If playerScore = 22 Then playerScore = 12
Console.WriteLine()
If playerScore = 21 And Not dealerScore = 21 Then

Console.WriteLine("BlackJack! You win.")

Console.WriteLine()

showCards("Dealer's hand: ", dealersHand)

ElseIf playerScore = 21 And dealerScore = 21 Then

showCards("Dealer's hand: ", dealersHand)

Console.WriteLine("It's a draw. No one wins.")

ElseIf (Not playerScore = 21 And Not dealerScore = 21) OrElse (Not playerScore = 21 And dealerScore = 21) Then

playGame("user", playerScore, dealerScore, playersHand, dealersHand)

End If
End If
Console.WriteLine()
Loop While playAgain.ToLower = "y"
End Sub

The playAHand Function prompts the player, asking whether to continue.

Private Function playAHand() As String

Console.WriteLine("Play a hand? (y/n)")

Dim response As String = Console.ReadLine

If response.ToLower = "y" Then

Console.Clear()

Console.WriteLine("Hands played: {0}", gamesPlayed)

Console.WriteLine("You won: {0}, Dealer won: {1}", youWon, dealerWon)

Console.WriteLine("Balance: {0:c2}", balance)
If balance = 0 Then

Console.WriteLine("Zero balance")

Return "n"

End If
Do

Console.WriteLine("How much would you like to bet?")

If Decimal.TryParse(Console.ReadLine, bet) AndAlso bet <= balance AndAlso bet > 0 Then

Console.WriteLine()

Console.WriteLine("Bet: {0:c2}", bet)

Exit Do

Else

Console.WriteLine()

Console.WriteLine("Invalid bet")

End If

Loop
End If
Return response
End Function

The playGame subroutine is the core of the game. This sub handles Twisting, recursively calling itself as well as branching out to the showCards and updateStats methods...

Private Sub playGame(ByVal player As String, ByVal score1 As Integer, ByVal score2 As Integer, ByVal hand1() As String, ByVal hand2() As String)
Dim response As String = ""

If player = "user" Then

Console.WriteLine("Twist? (y/n)")

Console.WriteLine()

Else

response = "y"

End If
If response.ToLower = "y" Then
hand1 = hand1.Concat(deal(1)).ToArray
If player = "user" Then

Console.WriteLine()

End If
score1 = hand1.Sum(Function(c) values.First(Function(v) If(Val(c) > 0, Val(c).ToString = v.cardName, c.StartsWith(v.cardName))).cardValue)
If player = "user" Then

If score1 > 21 And Not (score1 - (hand1.Count(Function(c) c.StartsWith("A")) * 10) <= 21) Then

showCards("Dealer's hand: ", If(player = "user", hand2, hand1))

Console.WriteLine()

ElseIf score1 > 21 And (score1 - (hand1.Count(Function(c) c.StartsWith("A")) * 10) <= 21) Then

Dim count As Integer = 0

While count < hand1.Count(Function(c) c.StartsWith("A")) And score1 > 21

count += 1

score1 -= 10

End While

If score1 < 21 Then

playGame("user", score1, score2, hand1, hand2)

Else

showCards("Dealer's hand: ", hand2)

End If

ElseIf score1 < 21 Then

playGame("user", score1, score2, hand1, hand2)

ElseIf score1 = 21 Then

playGame("dealer", score2, score1, hand2, hand1)

End If
Else
If score1 < 17 Then

playGame("dealer", score1, score2, hand1, hand2)

Else

If score1 < 20 Then

If r.Next(0, 4) = 1 Then

playGame("dealer", score1, score2, hand1, hand2)

Else

showCards("Dealer's hand: ", hand1)

End If

ElseIf score1 > 21 And (score1 - (hand1.Count(Function(c) c.StartsWith("A")) * 10) <= 21) Then

Dim count As Integer = 0

While count < hand1.Count(Function(c) c.StartsWith("A")) And score1 > 21

count += 1

score1 -= 10

End While

If score1 < 21 Then

playGame("dealer", score1, score2, hand1, hand2)

Else

showCards("Dealer's hand: ", hand1)

End If

Else

showCards("Dealer's hand: ", hand1)

End If

End If

End If

Else
If score2 < 17 Then

playGame("dealer", score2, score1, hand2, hand1)

Else

If score2 < 20 Then

If r.Next(0, 4) = 1 Then

playGame("dealer", score2, score1, hand2, hand1)

Else

showCards("Dealer's hand: ", hand2)

End If

Else

showCards("Dealer's hand: ", hand2)

End If

End If

End If

End Sub

The winner Function compares the scores and writes output to the Console.

Private Function winner(ByVal player As String, ByVal hand1() As String, ByVal hand2() As String) As String
Dim score1 As Integer = hand1.Sum(Function(c) values.First(Function(v) If(Val(c) > 0, Val(c).ToString = v.cardName, c.StartsWith(v.cardName))).cardValue)

Dim count As Integer = 0

While count < hand1.Count(Function(c) c.StartsWith("A")) And score1 > 21

count += 1

score1 -= 10

End While
Dim score2 As Integer = hand2.Sum(Function(c) values.First(Function(v) If(Val(c) > 0, Val(c).ToString = v.cardName, c.StartsWith(v.cardName))).cardValue)

count = 0

While count < hand2.Count(Function(c) c.StartsWith("A")) And score2 > 21

count += 1

score2 -= 10

End While
If player = "user" Then

If score1 <= 21 AndAlso score2 <= 21 Then

If score1 > score2 Then

Console.WriteLine("You win.")

Return "user"

ElseIf score2 > score1 Then

Console.WriteLine("Dealer wins.")

Return "dealer"

Else 'draw

Console.WriteLine("No one wins.")

Return "draw"

End If

Else

If score1 > 21 Then

Console.WriteLine("You bust. Dealer wins.")

Return "dealer"

Else 'score2 > 21

Console.WriteLine("Dealer bust. You win.")

Return "user"

End If

End If

Else '"dealer"

If score1 <= 21 AndAlso score2 <= 21 Then

If score2 > score1 Then

Console.WriteLine("You win.")

Return "user"

ElseIf score1 > score2 Then

Console.WriteLine("Dealer wins.")

Return "dealer"

Else 'draw

Console.WriteLine("No one wins.")

Return "draw"

End If

Else

If score2 > 21 Then

Console.WriteLine("You bust. Dealer wins.")

Return "dealer"

Else 'score1 > 21

Console.WriteLine("Dealer bust. You win.")

Return "user"

End If

End If

End If
End Function

The shuffle method, randomly shuffles the deck..

Private Sub shuffle()

deck = deck.OrderBy(Function(x) r.NextDouble).ToArray

End Sub

The deal Function takes the specified number of cards from the deck and returns them as a String Array...

Private Function deal(ByVal count As Integer) As String()

Dim a() As String = deck.Take(count).ToArray

deck = deck.Except(a).ToArray

Return a

End Function

The updateStats method updates the balance and statistics Variables in preparation for the next hand...

Private Sub updateStats(ByVal winner As String)

gamesPlayed += 1

youWon += If(winner = "user", 1, 0)

dealerWon += If(winner = "dealer", 1, 0)

balance += If(winner = "user", bet, If(winner = "dealer", -bet, 0))

End Sub

Finally the showCards method writes the contents of a hand to the Console, using appropriate symbols and coloring...

Private Sub showCards(ByVal label As String, ByVal cards() As String)

Console.Write(label)

Dim reds() As String = {Chr(3), Chr(4)}

For x As Integer = 0 To cards.GetUpperBound(0)

Console.ForegroundColor = If(reds.Any(Function(s) cards(x).Contains(s)), ConsoleColor.Red, ConsoleColor.Gray)

Console.Write(cards(x) & " ")

Next x
Dim cardSum As Integer = cards.Sum(Function(c) values.First(Function(v) If(Val(c) > 0, Val(c).ToString = v.cardName, c.StartsWith(v.cardName))).cardValue)

Dim count As Integer = 0

While count < cards.Count(Function(c) c.StartsWith("A")) And cardSum > 21

count += 1

cardSum -= 10

End While
Console.ForegroundColor = ConsoleColor.White
Console.Write("({0})", cardSum)

Console.WriteLine()
End Sub

## Articles related to game programming

VB.Net - WordSearch
VB.Net - Vertex
VB.Net - Perspective
VB.Net - MasterMind
VB.Net - OOP BlackJack
VB.Net - Numbers Game
VB.Net - HangMan
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