using System.Collections.Generic;
Console.WriteLine("Welcome to Blackjack!");
var cardDeck = new CardDeck();
var player = new Player(cardDeck);
var dealer = new Dealer(cardDeck);
CheckWinCondition(player, dealer);
private static void CheckWinCondition(Player player, Dealer dealer)
if (player.IsBusted && dealer.IsBusted)
Console.WriteLine("Draw! Both the player and the dealer busted.");
else if (dealer.IsBusted)
Console.WriteLine("Win! The dealer bust.");
else if (player.IsBusted)
Console.WriteLine("Lose! You bust.");
else if (player.HandTotal == dealer.HandTotal)
Console.WriteLine("Draw! You have the same score.");
else if (player.HandTotal > dealer.HandTotal)
Console.WriteLine("Win! You beat the dealer.");
Console.WriteLine("Lose! The dealer beat you.");
private readonly Hand _hand;
public Player(CardDeck cardDeck)
_hand = new Hand(cardDeck);
public int HandTotal => _hand.HandTotal;
public bool IsBusted => _hand.IsBusted;
Console.WriteLine($"Your hand: {string.Join(", ", _hand.Cards.Select(card => card.Type))} ({_hand.HandTotal})");
Console.WriteLine("Please enter your choice (hit or call)");
var input = Console.ReadLine().ToLowerInvariant();
if (input is "h" or "hit")
var drawnCard = _hand.DrawCard();
Console.WriteLine($"You drew a {drawnCard.Type}, your new hand total is {_hand.HandTotal}");
else if (input is "c" or "call")
private readonly Hand _hand;
public Dealer(CardDeck cardDeck)
_hand = new Hand(cardDeck);
public int HandTotal => _hand.HandTotal;
public bool IsBusted => _hand.IsBusted;
Console.WriteLine($"Dealer's hand: {string.Join(", ", _hand.Cards.Select(card => card.Type))} ({_hand.HandTotal})");
while (!IsBusted && _hand.HandTotal <= 16)
var drawnCard = _hand.DrawCard();
Console.WriteLine($"Dealer drew a {drawnCard.Type}, their new hand total is {_hand.HandTotal}");
private readonly CardDeck _cardDeck;
private readonly List<Card> _hand;
public Hand(CardDeck cardDeck)
_hand = [ cardDeck.DrawCard(), cardDeck.DrawCard() ];
HandTotal = GetHandTotal();
public int HandTotal { get; private set; }
public IReadOnlyList<Card> Cards => _hand.AsReadOnly();
public bool IsBusted => IsHandBusted(HandTotal);
var card = _cardDeck.DrawCard();
HandTotal = GetHandTotal();
private int GetHandTotal()
var handTotal = _hand.Sum(card => card.Value);
if (IsHandBusted(handTotal))
var numberOfAces = _hand.Count(card => card.Type == CardType.Ace);
for (int i = 0; i < numberOfAces && IsHandBusted(handTotal); i++)
private static bool IsHandBusted(int handTotal)
private readonly Random _random;
private readonly Stack<Card> _cards;
_cards = InitializeDeck();
private Stack<Card> InitializeDeck()
var allCards = new List<Card>();
foreach (var cardType in Enum.GetValues<CardType>())
Value = GetCardValue(cardType),
for (int i = 0; i < 4; i++)
return new Stack<Card>(allCards);
private void Shuffle(List<Card> cards)
for (var i = 0; i < 100; i++)
var oldCardIndex = _random.Next(0, cards.Count);
var newCardIndex = _random.Next(0, cards.Count);
var oldCard = cards[oldCardIndex];
var newCard = cards[newCardIndex];
cards[oldCardIndex] = newCard;
cards[newCardIndex] = oldCard;
private static int GetCardValue(CardType cardType)
CardType.Jack or CardType.Queen or CardType.King => 10,
public CardType Type { get; init; }
public int Value { get; init; }