-1

I created a Blackjack game for coding school and I'm modifying it to display other aspects of the game, like what card value total the dealer had and what value total I had at the end of the game. It all works well until the Dealer Busted and I'm getting this error:

System.InvalidOperationException: 'Sequence contains no elements'

I've googled and searched Stackoverflow, but I didn't understand any of the responses. Here's my github code for it. https://github.com/CrystalReimche/TwentyOneGame

In the TwentyOneGame.cs, line 143 is where where I'm trying to get it to display.

            foreach (KeyValuePair<Player, int> entry in Bets)
            {
                Players.Where(x => x.Name == entry.Key.Name).First().Balance += (entry.Value * 2);
                Console.WriteLine($"{entry.Key.Name} won {entry.Value} and now has a balance of {entry.Key.Balance}!");
                Console.WriteLine($"Dealer had {TwentyOneRules.DealerCardValue(Dealer.Hand)} and {entry.Key.Name} had {TwentyOneRules.PlayerCardValue(entry.Key.Hand)}");
            }

In the TwentyOneRules.cs holds the methods for it.

  public static Dictionary<Face, int> _cardValues = new Dictionary<Face, int>()
    {
        [Face.Two] = 2,
        [Face.Three] = 3,
        [Face.Four] = 4,
        [Face.Five] = 5,
        [Face.Six] = 6,
        [Face.Seven] = 7,
        [Face.Eight] = 8,
        [Face.Nine] = 9,
        [Face.Ten] = 10,
        [Face.Jack] = 10,
        [Face.Queen] = 10,
        [Face.King] = 10,
        [Face.Ace] = 1
    };

    public static int[] GetAllPossibleHandValues(List<Card> Hand)
    {
        int aceCount = Hand.Count(x => x.Face == Face.Ace); // Find out how many Ace's there are
        int[] result = new int[aceCount + 1]; // Plus 1 means if there's 2 Aces, there's 3 possible results ((1,1)||(1,11)||(11,11))
        int value = Hand.Sum(x => _cardValues[x.Face]); // Value is the lowest possible value with all Ace's == 1
        result[0] = value;
        if (result.Length == 1) return result;
        for (int i = 1; i < result.Length; i++)
        {
            value += (i * 10);
            result[i] = value;
        }
        return result;
    }

    public static bool CheckForBlackJack(List<Card> Hand)
    {
        int[] possibleValues = GetAllPossibleHandValues(Hand);
        int value = possibleValues.Max();
        if (value == 2) return true;
        else return false;
    }

    public static bool IsBusted(List<Card> Hand)
    {
        int value = GetAllPossibleHandValues(Hand).Min();
        if (value > 21) return true;
        else return false;
    }

    public static bool ShouldDealerStay(List<Card> Hand)
    {
        int[] possibleHandvalues = GetAllPossibleHandValues(Hand);
        foreach (int value in possibleHandvalues)
        {
            if (value > 16 && value < 22)
            {
                return true;
            }
        }
        return false;
    }

    public static bool? CompareHands(List<Card> PlayerHand, List<Card> DealerHand)
    {
        int[] playerResults = GetAllPossibleHandValues(PlayerHand);
        int[] dealerResults = GetAllPossibleHandValues(DealerHand);

        int playerScore = playerResults.Where(x => x < 22).Max(); // Filter the values that's < 22 and bring me the max of the values
        int dealerScore = dealerResults.Where(x => x < 22).Max();

        if (playerScore > dealerScore) return true;
        else if (playerScore < dealerScore) return false;
        else return null; // this is a tie
    }

    public static int PlayerCardValue(List<Card> PlayerHand)
    {
        int[] playerResults = GetAllPossibleHandValues(PlayerHand);
        int playerScore = playerResults.Where(x => x < 50).Max();
        return playerScore;
    }

    public static int DealerCardValue(List<Card> DealerHand)
    {
        int[] dealerResults = GetAllPossibleHandValues(DealerHand);
        int dealerScore = dealerResults.Where(x => x < 22).Max();
        return dealerScore; 
    }

I'm thinking it has something to do with the Dictionary, since the methods work on other parts of the game that do not use the Dictionary. For example, if I busted, it would display my card value total and the dealer card value total.

if (busted)
                {
                    Console.WriteLine($"{player.Name} Busted!  You lose your bet of {Bets[player]}.  Your balance is now {player.Balance}");
                    Console.WriteLine($"Dealer had {TwentyOneRules.DealerCardValue(Dealer.Hand)} and {player.Name} had {TwentyOneRules.PlayerCardValue(player.Hand)}");

                }

I just don't have a good grasp on how to use the Dictionary properly yet.

  • 2
    First: you need to post a [mcve]. That means all relevant code must be **here**, not on GitHub. Second, you need to learn to debug your code, step through it and see what happens. – Camilo Terevinto Apr 01 '18 at 00:23

1 Answers1

1

The problem is that you're invoking Max() (in either DealerCardValue or PlayerCardValue) on a sequence which contains no elements, as the Where() return value is an empty sequence, therefore there's no max value. This is written in the Max() function's documentation in MSDN.

Add DefaultIfEmpty() before Max() in DealerCardValue and PlayerCardValue to prevent InvalidOperationException from being thrown, as shown here, like so:

public static int DealerCardValue(List<Card> DealerHand)
{
    int[] dealerResults = GetAllPossibleHandValues(DealerHand);
    int dealerScore = dealerResults.Where(x => x < 22).DefaultIfEmpty().Max();
    return dealerScore;
}
Amit Beckenstein
  • 1,220
  • 12
  • 20