# 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 player and dealer, meaning that players compete against the dealer rather than 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 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.

`static` `string``[] deck;`
`static` `Random r = ``new` `Random();`
`private` `struct` ``` value```
`{`
` ``public` `string` ``` cardName;```
` ``public` `int` ``` cardValue;```
` ``public` `value(``string` `cn, ``int` `cv)`
`  ``{`
` ``this``.cardName = cn;`
` ``this``.cardValue = cv;`
`  ``}`
```} ```
`static` `List<value> values = ``new` `List<value>();`
`static` `int` ``` gamesPlayed;```
`static` `int` ``` youWon;```
`static` `int` ``` dealerWon;```
` `
`static` `decimal` ``` balance = 100m;```
`static` `decimal` ``` bet;```
`In Sub Main, the suits Arrays are loaded, and also the values List. then the game loop begins.`
`static` `void` ``` Main(````string``[] args)`
```{ ```
`  ``string``[] hearts = Enumerable.Range(2, 9).Select(x => x.ToString() + (Char)3).ToArray();`
`  ``hearts = hearts.Concat(``new` `string``[] {`
` ``"J"` `+ (Char)3,`
` ``"Q"` `+ (Char)3,`
` ``"K"` `+ (Char)3,`
` ``"A"` `+ (Char)3`
`  ````}).ToArray(); ```
`  ``string````[] diamonds = Enumerable.Range(2, 9).Select(x => x.ToString() + (Char)4).ToArray();```
`  ``diamonds = diamonds.Concat(``new` `string``[] {`
` ``"J"` `+ (Char)4,`
` ``"Q"` `+ (Char)4,`
` ``"K"` `+ (Char)4,`
` ``"A"` `+ (Char)4`
`  ````}).ToArray(); ```
`  ``string``[] clubs = Enumerable.Range(2, 9).Select(x => x.ToString() + (Char)5).ToArray();`
`  ``clubs = clubs.Concat(``new` `string``[] {`
` ``"J"` `+ (Char)5,`
` ``"Q"` `+ (Char)5,`
` ``"K"` `+ (Char)5,`
` ``"A"` `+ (Char)5`
`  ``}).ToArray();`
` ``string``[] spades = Enumerable.Range(2, 9).Select(x => x.ToString() + (Char)6).ToArray();`
`  ``spades = spades.Concat(``new` `string``[] {`
` ``"J"` `+ (Char)6,`
` ``"Q"` `+ (Char)6,`
` ``"K"` `+ (Char)6,`
` ``"A"` `+ (Char)6`
`  ````}).ToArray(); ```
`  ``values.Add(``new` `value(``"2"``, 2));`
`  ``values.Add(``new` `value(``"3"``, 3));`
`  ``values.Add(``new` `value(``"4"``, 4));`
`  ``values.Add(``new` `value(``"5"``, 5));`
`  ``values.Add(``new` `value(``"6"``, 6));`
`  ``values.Add(``new` `value(``"7"``, 7));`
`  ``values.Add(``new` `value(``"8"``, 8));`
`  ``values.Add(``new` `value(``"9"``, 9));`
`  ``values.Add(``new` `value(``"10"``, 10));`
`  ``values.Add(``new` `value(``"J"``, 10));`
`  ``values.Add(``new` `value(``"Q"``, 10));`
`  ``values.Add(``new` `value(``"K"``, 10));`
`  ``values.Add(``new` `value(``"A"``, 11));`
` `
`  ``string` `playAgain = ``null````; ```
`  ``do`
`  ``{`
`  ````playAgain = balance > 0 ? playAHand() : ````"n"``; `
` ``if` `(playAgain.ToLower() == ``"y"``)`
`  ``{`
`  ``deck = hearts.Concat(diamonds).Concat(clubs).Concat(spades).ToArray();`
`  ````shuffle(); ```
` ``string``[] dealersHand = deal(2);`
` ``string````[] playersHand = deal(2); ```
` ``int` `dealerScore = dealersHand.Sum(c => values.First(v => val(c) > 0 ? val(c).ToString() == v.cardName : c.StartsWith(v.cardName)).cardValue);`
` ``if` `(dealerScore == 22)`
`  ``dealerScore = 12;`
` ``int` `playerScore = playersHand.Sum(c => values.First(v => val(c) > 0 ? val(c).ToString() == v.cardName : c.StartsWith(v.cardName)).cardValue);`
` ``if` `(playerScore == 22)`
`  ````playerScore = 12; ```
` ``showCards(``"Your hand: "````, playersHand); ```
` ````Console.WriteLine(); ```
` ``if` `(playerScore == 21 & !(dealerScore == 21))`
`  ``{`
` ``Console.WriteLine(``"BlackJack! You win."``);`
` ``Console.WriteLine();`
`  ``showCards(``"Dealer's hand: "``, dealersHand);`
`  ``updateStats(``"user"``);`
`  ``}`
` ``else` `if` ``` (playerScore == 21 & dealerScore == 21)```
`  ``{`
`  ``showCards(``"Dealer's hand: "``, dealersHand);`
` ``Console.WriteLine(``"It's a draw. No one wins."``);`
`  ``updateStats(``"draw"``);`
`  ``}`
` ``else` `if` ``` ((!(playerScore == 21) & !(dealerScore == 21)) || (!(playerScore == 21) & dealerScore == 21))```
`  ``{`
`  ``playGame(``"user"``, playerScore, dealerScore, playersHand, dealersHand);`
`  ``}`
`  ``}`
` ``Console.WriteLine();`
`  ````} ````while` ``` (playAgain.ToLower() == ````"y"``);`
` ``Console.ReadLine();`
`}`

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

`private` `static` ``` string``` `playAHand()`
`{`
` ``Console.WriteLine(``"Play a hand? (y/n)"``);`
` ``string` `response = Console.ReadLine();`
` ``if` `(response.ToLower() == ``"y"``)`
`  ``{`
` ``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)`
`  ``{`
` ``Console.WriteLine(``"Zero balance"``);`
` ``return` `"n"``;`
`  ``}`
` `
`  ``do`
`  ``{`
` ``Console.WriteLine(``"How much would you like to bet?"``);`
` ``if` `(``decimal````.TryParse(Console.ReadLine(), ````out` ``` bet) && bet <= balance && bet > 0)```
`  ``{`
` ``Console.WriteLine();`
` ``Console.WriteLine(``"Bet: {0:c2}"``, bet);`
` ``break``;`
`  ``}`
` ``else`
`  ``{`
` ``Console.WriteLine();`
` ``Console.WriteLine(``"Invalid bet"``);`
`  ``}`
`  ````} ````while` ``` (````true``);`
`  ``}`
`  ``return` `response;`
`}`
`private` `static` ``` string``` `playAHand()`
`{`
` ``Console.WriteLine(``"Play a hand? (y/n)"``);`
` ``string` `response = Console.ReadLine();`
` ``if` `(response.ToLower() == ``"y"``)`
`  ``{`
` ``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)`
`  ``{`
` ``Console.WriteLine(``"Zero balance"``);`
` ``return` `"n"``;`
`  ``}`
` `
`  ``do`
`  ``{`
` ``Console.WriteLine(``"How much would you like to bet?"``);`
` ``if` `(``decimal````.TryParse(Console.ReadLine(), ````out` ``` bet) && bet <= balance && bet > 0)```
`  ``{`
` ``Console.WriteLine();`
` ``Console.WriteLine(``"Bet: {0:c2}"``, bet);`
` ``break``;`
`  ``}`
` ``else`
`  ``{`
` ``Console.WriteLine();`
` ``Console.WriteLine(``"Invalid bet"``);`
`  ``}`
`  ````} ````while` ``` (````true``);`
`  ``}`
`  ``return` `response;`
`}`

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` `static` ``` void``` `playGame(``string` `player, ``int` `score1, ``int` `score2, ``string````[] hand1, ````string``[] hand2)`
`  ``{`
` ``string` `response = ``""``;`
` ``if` `(player == ``"user"``)`
`  ``{`
` ``Console.WriteLine(``"Twist? (y/n)"``);`
`  ``response = Console.ReadLine();`
` ``Console.WriteLine();`
`  ``}`
` ``else`
`  ``{`
`  ````response = ````"y"``;`
`  ````} ```
`  ``if` `(response.ToLower() == ``"y"``)`
`  ``{`
`  ``hand1 = hand1.Concat(deal(1)).ToArray();`
` `
`  ``if` `(player == ``"user"``)`
`  ``{`
`  ``showCards(``"Your hand: "``, hand1);`
` ``Console.WriteLine();`
`  ````} ```
`  ````score1 = hand1.Sum(c => values.First(v => val(c) > 0 ? val(c).ToString() == v.cardName : c.StartsWith(v.cardName)).cardValue); ```
`  ``if` `(player == ``"user"``)    {`
`  ``if` `(score1 > 21 & !(score1 - (hand1.Count(c => c.StartsWith(``"A"``)) * 10) <= 21))`
`  ``{`
`  ``showCards(``"Dealer's hand: "````, player == ````"user"` `? hand2 : hand1);`
` ``Console.WriteLine();`
`  ``updateStats(winner(player, hand1, hand2));`
`  ``}`
` ``else` `if` ``` (score1 > 21 & (score1 - (hand1.Count(c => c.StartsWith(````"A"``)) * 10) <= 21))`
`  ``{`
` ``int` `count = 0;`
` ``while` `(count < hand1.Count(c => c.StartsWith(``"A"``)) & score1 > 21)`
`  ``{`
`  ``count += 1;`
`  ``score1 -= 10;`
`  ``}`
` ``if` `(score1 < 21)`
`  ``{`
`  ``playGame(``"user"``, score1, score2, hand1, hand2);`
`  ``}`
` ``else`
`  ``{`
`  ``showCards(``"Dealer's hand: "``, hand2);`
`  ``updateStats(winner(player, hand1, hand2));`
`  ``}`
`  ``}`
` ``else` `if` ``` (score1 < 21)```
`  ``{`
`  ``playGame(``"user"``, score1, score2, hand1, hand2);`
`  ``}`
` ``else` `if` ``` (score1 == 21)```
`  ``{`
`  ``playGame(``"dealer"``, score2, score1, hand2, hand1);`
`  ``}`
`  ``}`
` ``else`
`  ``{`
` ``if` `(score1 < 17)`
`  ``{`
`  ``playGame(``"dealer"``, score1, score2, hand1, hand2);`
`  ``}`
` ``else`
`  ``{`
` ``if` `(score1 < 20)`
`  ``{`
` ``if` `(r.Next(0, 4) == 1)`
`  ``{`
`  ``playGame(``"dealer"``, score1, score2, hand1, hand2);`
`  ``}`
` ``else`
`  ``{`
`  ``showCards(``"Dealer's hand: "``, hand1);`
`  ``updateStats(winner(player, hand1, hand2));`
`  ``}`
`  ``}`
` ``else` `if` ``` (score1 > 21 & (score1 - (hand1.Count(c => c.StartsWith(````"A"``)) * 10) <= 21))`
`  ``{`
` ``int` `count = 0;`
` ``while` `(count < hand1.Count(c => c.StartsWith(``"A"``)) & score1 > 21)`
`  ``{`
`  ``count += 1;`
`  ``score1 -= 10;`
`  ``}`
` ``if` `(score1 < 21)`
`  ``{`
`  ``playGame(``"dealer"``, score1, score2, hand1, hand2);`
`  ``}`
` ``else`
`  ``{`
`  ``showCards(``"Dealer's hand: "``, hand1);`
`  ``updateStats(winner(player, hand1, hand2));`
`  ``}`
`  ``}`
` ``else`
`  ``{`
`  ``showCards(``"Dealer's hand: "``, hand1);`
`  ``updateStats(winner(player, hand1, hand2));`
`  ``}`
`  ``}`
`  ``}`
`  ``}`
` ``else`
`  ``{`
` ``if` `(score2 < 17)`
`  ``{`
`  ``playGame(``"dealer"``, score2, score1, hand2, hand1);`
`  ``}`
` ``else`
`  ``{`
` ``if` `(score2 < 20)`
`  ``{`
` ``if` `(r.Next(0, 4) == 1)`
`  ``{`
`  ``playGame(``"dealer"``, score2, score1, hand2, hand1);`
`  ``}`
` ``else`
`  ``{`
`  ``showCards(``"Dealer's hand: "``, hand2);`
`  ``updateStats(winner(player, hand1, hand2));`
`  ``}`
`  ``}`
` ``else`
`  ``{`
`  ``showCards(``"Dealer's hand: "``, hand2);`
`  ``updateStats(winner(player, hand1, hand2));`
`  ``}`
`  ``}`
`  ``}`
`}`

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

`private` `static` ``` string``` `winner(``string` `player, ``string````[] hand1, ````string``[] hand2)`
`{`
` ``int` `score1 = hand1.Sum(c => values.First(v => val(c) > 0 ? val(c).ToString() == v.cardName`
```:c.StartsWith(v.cardName)).cardValue); ```
`  ``int` `count = 0;`
` ``while` `(count < hand1.Count(c => c.StartsWith(``"A"``)) & score1 > 21)`
`  ``{`
`  ``count += 1;`
`  ``score1 -= 10;`
`  ``}`
` ``int` ```score2 = hand2.Sum(c => values.First(v => val(c) > 0 ? val(c).ToString() == v.cardName : c.StartsWith(v.cardName)).cardValue); ```
`  ``count = 0;`
` ``while` `(count < hand2.Count(c => c.StartsWith(``"A"``)) & score2 > 21)`
`  ``{`
`  ``count += 1;`
`  ``score2 -= 10;`
`  ````} ```
`  ``if` `(player == ``"user"``)`
`  ``{`
` ``if` `(score1 <= 21 && score2 <= 21)`
`  ``{`
` ``if` `(score1 > score2)`
`  ``{`
` ``Console.WriteLine(``"You win."``);`
` ``return` `"user"``;`
`  ``}`
` ``else` `if` ``` (score2 > score1)```
`  ``{`
` ``Console.WriteLine(``"Dealer wins."``);`
` ``return` `"dealer"``;`
`  ``}`
` ``else`
`  ``{`
` ``//draw`
` ``Console.WriteLine(``"No one wins."``);`
` ``return` `"draw"``;`
`  ``}`
`  ``}`
` ``else`
`  ``{`
` ``if` `(score1 > 21)`
`  ``{`
` ``Console.WriteLine(``"You bust. Dealer wins."``);`
` ``return` `"dealer"``;  `
`  ``}`
` ``else`
`  ``{`
` ``//score2 > 21`
` ``Console.WriteLine(``"Dealer bust. You win."``);`
` ``return` `"user"``;`
`  ``}`
`  ``}`
`  ``}`
` ``else`
`  ``{`
` ``//dealer`
` ``if` `(score1 <= 21 && score2 <= 21)`
`  ``{`
` ``if` `(score2 > score1)`
`  ``{`
` ``Console.WriteLine(``"You win."``);`
` ``return` `"user"``;`
`  ``}`
` ``else` `if` ``` (score1 > score2)```
`  ``{`
` ``Console.WriteLine(``"Dealer wins."``);`
` ``return` `"dealer"``;`
`  ``}`
` ``else`
`  ``{`
` ``//draw`
` ``Console.WriteLine(``"No one wins."``);`
` ``return` `"draw"``;`
`  ``}`
`  ``}`
` ``else`
`  ``{`
` ``if` `(score2 > 21)`
`  ``{`
` ``Console.WriteLine(``"You bust. Dealer wins."``);`
` ``return` `"dealer"``;  `
`  ``}`
` ``else`
`  ``{`
` ``//score1 > 21`
` ``Console.WriteLine(``"Dealer bust. You win."``);`
` ``return` `"user"``;`
`  ``}`
`  ``}`
`  ``}`
`}`

The shuffle method, randomly shuffles the deck.

`private` `static` ``` void``` `shuffle()`
`{`
`  ``deck = deck.OrderBy(x => r.NextDouble()).ToArray();`
`}`

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

`private` `static` ``` string````[] deal(``int` `count)`
`{`
` ``string``[] a = deck.Take(count).ToArray();`
`  ``deck = deck.Except(a).ToArray();`
` ``return` `a;`
`}`

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

`private` `static` ``` void``` `updateStats(``string` `winner)`
`{`
`  ``gamesPlayed += 1;`
`  ````youWon += winner == ````"user"` `? 1 : 0;`
`  ````dealerWon += winner == ````"dealer"` `? 1 : 0;`
`  ````balance += winner == ````"user"` ```? bet : winner == ````"dealer"` `? -bet : 0;`
`}`

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

`private` `static` ``` void``` `showCards(``string` `label, ``string``[] cards)`
`{`
` ``Console.Write(label);`
` ``char``[] reds = { (Char)3, (Char)4 };`
` ``for` `(``int` `x = 0; x <= cards.GetUpperBound(0); x++)`
`  ``{`
` ``Console.ForegroundColor = reds.Any(s => cards[x].Contains(s)) ? ConsoleColor.Red : ConsoleColor.Gray;`
` ````Console.Write(cards[x] + ````" "``);`
`  ````} ```
`  ``int` ```cardSum = cards.Sum(c => values.First(v => val(c) > 0 ? val(c).ToString() == v.cardName : c.StartsWithv.cardName)).cardValue); ```
`  ``int` `count = 0;`
` ``while` `(count < cards.Count(c => c.StartsWith(``"A"``)) & cardSum > 21)`
`  ``{`
`  ``count += 1;`
`  ``cardSum -= 10;`
`  ````} ```
`  ````Console.ForegroundColor = ConsoleColor.White; ```
`  ``Console.Write(``"({0})"``, cardSum);`
` ``Console.WriteLine();`
`}`

Finally the val Function which is used when identifying card values.

`private static int val(string c)`
`{`
` ``string` `faceValue = c.Replace(((Char)3).ToString(), ``""````).Replace(((Char)4).ToString(), ````""````).Replace(((Char)5).ToString(), ````""````).Replace(((Char)6).ToString(), ````""``);`
` ``int` `value;`
` ````Int32.TryParse(faceValue, ````out` ``` value);```
` ``return` `value;`
`}`

## 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