This is my revised command line Blackjack code. I tried to use as many suggestions as possible and ended up with this code. I also uploaded the project to GitHub if someone is interested.
The Dealer
is now a bit smarter. The game now uses a card stack of 5 decks (which is easy to change), which is shuffled properly.
I'm not sure if I succeeded in using the naming convention that was spoken about in my last Post.
In the final version I want to implement a Betting system and the possibility for more players.
I hope to get suggestions on better class structuring/using, as well as clean coding (I think the _DecideWinner
function in Game.cs can be done much cleaner and better).
Programm.cs
namespace CliBlackjack
{
class Program
{
static void Main(string[] args)
{
Game game = new Game();
while (game.moreGames)
{
game.PlayGame();
}
}
}
}
Card.cs
namespace CliBlackjack
{
enum Suit
{
Spades,
Hearths,
Clubs,
Diamonds,
};
enum Rank
{
Ace,
Two,
Three,
Four,
Five,
Six,
Seven,
Eight,
Nine,
Ten,
Jack,
Quen,
King,
};
class Card
{
public Rank rank;
public Suit suit;
public Card(int Rank, int Suit)
{
rank = (Rank)Rank;
suit = (Suit)Suit;
}
}
}
Player.cs
using System.Collections.Generic;
namespace CliBlackjack
{
class Player
{
public int handTotal=0;
public string name;
public bool draw=true;
public bool Busted = false;
public List<Card> hand = new List<Card>();
public Player(string Name)
{
name = Name;
}
public void GetCards(List<Card> Deck)
{
hand.Add(Deck[0]);
Deck.RemoveAt(0);
_CalcHandTotal();
}
private void _CalcHandTotal()
{
handTotal = 0;
int aceCount = 0;
foreach (var card in hand)
{
if (card.rank == 0)
{
aceCount++;
}
else if ((int)card.rank < 10)
{
handTotal += (int)card.rank+1;
}
else
{
handTotal += 10;
}
}
if (aceCount > 0)
{
if (handTotal <= (11 - aceCount))
{
handTotal += (aceCount - 1) + 11;
}
else
{
handTotal += aceCount;
}
}
}
}
}
Deck.cs
using System;
using System.Collections.Generic;
using System.Linq;
namespace CliBlackjack
{
class Deck
{
private int _deckCount;
public List<Card> deck = new List<Card>();
Random rnd = new Random();
public void CreateDeck(int DeckCount)
{
//removes the remaining Contents of the deck, once a new deck is needed
deck.Clear();
_deckCount = DeckCount;
//Itterate for the given amount of Decks
for (int i = 0; i < _deckCount; i++)
{
//Itterate over Card Ranks
for (int x = 0; x < 13; x++)
{
//Itterate over Card Suites
for (int z = 0; z < 4; z++)
{
deck.Add(new Card(x, z));
}
}
}
}
public void Shuffle(int TimesToShuffle)
{
for (int i = 0; i < TimesToShuffle; i++)
{
//Fisher Yates Shuffle
for (int cardIndex1 = deck.Count() - 1; cardIndex1 > 0; cardIndex1--)
{
int cardIndex2 = rnd.Next(cardIndex1 + 1);
var tmp = deck[cardIndex1];
deck[cardIndex1] = deck[cardIndex2];
deck[cardIndex2] = tmp;
}
}
}
}
}
Game.cs
using System;
namespace CliBlackjack
{
class Game
{
public bool moreGames = true;
public void PlayGame()
{
string choice="";
Console.Clear();
Player player1 = new Player("Player");
Player dealer = new Player("Dealer");
Deck gameDeck = new Deck();
gameDeck.CreateDeck(5);
gameDeck.Shuffle(10);
_GetStartingHand(player1, gameDeck);
_GetStartingHand(dealer, gameDeck);
_DisplayHand(dealer);
_DisplayHand(player1);
_CheckHand(player1);
_CheckHand(dealer);
if (!(player1.Busted || dealer.Busted))
{
_DrawPhase(player1, dealer, gameDeck);
}
_DecideWinner(player1, dealer);
Console.Write("\n Play again? (Y/N): ");
choice = Console.ReadLine();
moreGames = choice.ToUpper() != "N";
}
//this doesnt seem to be the best way to decide the winner, works for now.
private void _DecideWinner(Player Player, Player Dealer)
{
if (Player.handTotal == 21 && Dealer.handTotal == 21)
{
Console.WriteLine("\n It's a tie!");
}
else if (Player.handTotal == 21 && Dealer.handTotal != 21)
{
Console.WriteLine($"\n {Player.name} wins!");
}
else if (Player.handTotal != 21 && Dealer.handTotal == 21)
{
Console.WriteLine($"\n {Dealer.name} wins!");
}
else if (Player.handTotal > 21 && Dealer.handTotal <= 21)
{
Console.WriteLine($"\n {Dealer.name} wins!");
}
else if (Player.handTotal <= 21 && Dealer.handTotal > 21)
{
Console.WriteLine($"\n {Player.name} wins!");
}
else if (Player.handTotal > 21 && Dealer.handTotal > 21)
{
Console.WriteLine($"\n Both Busted ");
}
else if (Player.handTotal> Dealer.handTotal)
{
Console.WriteLine($"\n {Player.name} wins!");
}
else if (Player.handTotal < Dealer.handTotal)
{
Console.WriteLine($"\n {Dealer.name} wins!");
}
else if (Player.handTotal == Dealer.handTotal)
{
Console.WriteLine("\n It's a tie!");
}
}
private void _DrawPhase(Player Player, Player Dealer, Deck Deck)
{
while (Player.draw)
{
Console.Write("\n Would you like to (H)it or (S)tand: ");
string choice = Console.ReadLine();
Player.draw = choice.ToUpper() != "S";
if (Player.draw)
{
_CardDraw(Player, Deck);
_DisplayBoard(Player, Dealer);
_CheckHand(Player);
}
}
if (!(Player.Busted))
{
Dealer.draw = Dealer.handTotal < 16;
while (Dealer.draw)
{
_CardDraw(Dealer, Deck);
_DisplayBoard(Player, Dealer);
_CheckHand(Dealer);
Dealer.draw = Dealer.handTotal < 16;
}
Console.Clear();
_DisplayBoard(Player, Dealer);
_CheckHand(Player);
_CheckHand(Dealer);
}
}
private void _DisplayBoard(Player Player, Player Dealer)
{
_DisplayHand(Dealer);
_DisplayHand(Player);
}
private void _DisplayHand(Player Player)
{
Console.WriteLine("\n***********************\n" +
$"* {Player.name}Hand *\n" +
"***********************\n");
foreach (var card in Player.hand)
{
Console.WriteLine($" - {card.rank} of {card.suit}");
}
Console.WriteLine($"\n Total: {Player.handTotal}");
}
private void _GetStartingHand(Player Player, Deck Deck)
{
Player.GetCards(Deck.deck);
Player.GetCards(Deck.deck);
}
private void _CardDraw(Player Player,Deck Deck)
{
Console.Clear();
Player.GetCards(Deck.deck);
}
private void _CheckHand(Player Player)
{
if (Player.handTotal > 21)
{
Console.WriteLine($"\n {Player.name} Busted!");
Player.draw = false;
Player.Busted = true;
}
else if (Player.handTotal == 21)
{
Console.WriteLine($"\n {Player.name} got a Blackjack!");
Player.draw = false;
}
}
}
}