Search code examples
c#user-interfaceblackjack

Properties are not being used - BlackJack Project (always same !false! result but it should be different)


I am currently coding a BlackJack Game, and now I am at the Sprint for the HAND and the thing is that the Hand has a HandVALUE and a HandRATING. This Value or Rating represent the Handsproperties or fields. The problem is (you will se it more in the code) that when I create a new HAND in the Console.NetFramework (UI) and type Console.WriteLine(Console.WriteLine("The Value of the hand is: " + hand.HandValue); or Console.WriteLine("The Rating of the hand is: " + hand.HandRating); that they always are 0 and None. 0 = HandValue and None is the HandRating. But they should have other Values and Ratings because (as you will see in the code) there are 3 cards with the value of 7 each = HANDVALUE : 21 and the HandRating should be TripleSeven (because we have 3 7-value cards). The Properties should be used and should set the HandValue and HandRating. (The code is very shortly shown here. If I would left something behind no one would understand the problem and code constructions)

Console.WriteLine("HAND - TESTS");
Hand hand = new Hand();
Console.WriteLine("First, output of the cards in the hand at the beginning. If their is nothing to see, the test" +
    "is positive.");
ICard card3 = new Card(CardValue.Seven, CardSuit.Heart);
ICard card4 = new Card(CardValue.Seven, CardSuit.Spade);
ICard card5 = new Card(CardValue.Seven, CardSuit.Diamond);

Console.WriteLine("");
Console.WriteLine("Press <ENTER> to add one card to the hand:");
Console.ReadLine();
hand.AddCard(card3);
Console.WriteLine("If there is only one card ---> then this hand function is working.");
hand.CardsInHandConsole();

Console.WriteLine("Press <ENTER> to add the next card:");
Console.ReadLine();
hand.AddCard(card4);
hand.AddCard(card5);
Console.WriteLine("If there are 3 cards ---> then this hand function is working.");
hand.CardsInHandConsole();
Console.WriteLine("Press <ENTER> to continue:");
Console.ReadLine();
Console.WriteLine("The Value of the hand is: " + hand.HandValue);
Console.WriteLine("The Rating of the hand is: " + hand.HandRating);

The hand class and the last down ENUM HandRating:

public class Hand
{
    private List<ICard> _cardsInHand = new List<ICard>();
    private int _handValue;
    private HandRating _handRating;


    public int HandValue
    {
        get
        {
            return _handValue;
        }
        set
        {
            CalculateHandValue();
        }
    }

    public HandRating HandRating
    {
        get
        {
            return _handRating;
        }
        set
        {
            //TripleSeven
            if (_cardsInHand[0].Value == CardValue.Seven &&
                _cardsInHand[1].Value == CardValue.Seven && 
                _cardsInHand[2].Value == CardValue.Seven)
            {
                _handRating = HandRating.TripleSeven;

            }
            //BlackJack
            else if (_cardsInHand[0].Value == CardValue.Jack &&
                     _cardsInHand[1].Value == CardValue.Ace)
            {
                _handRating = HandRating.BlackJack;

            }
            //Busted
            else if (_handValue > 21)
            {
                _handRating = HandRating.Busted;

            }
            //None      
            else { 

                _handRating = HandRating.None;

            }

        }
    }

    public IEnumerable<ICard> CardsInHand
    {
        get
        {
            return _cardsInHand;
        }
    }

    public void CardsInHandConsole()
    {
        foreach (ICard card in _cardsInHand)
        {
            Console.WriteLine(card.ToString());
        }
    }

    public void AddCard(ICard card)
    {
        _cardsInHand.Add(card);
    }

    public void ClearHand()
    {
        _cardsInHand.Clear();
        _handValue = 0;
        _handRating = HandRating.None;
    }

    private void CalculateHandValue()
    {
        for (int i = 0; i <= _cardsInHand.Count(); i++)
        {
            ReturnValue(i);
        }
    }

    public void ReturnValue(int index)
    {
        if (_cardsInHand[index].Value == CardValue.Two)
        {
            _handValue =+2;
        }
        else if (_cardsInHand[index].Value == CardValue.Three)
        {
            _handValue =+3;
        }
        else if (_cardsInHand[index].Value == CardValue.Four)
        {
            _handValue =+4;
        }
        else if (_cardsInHand[index].Value == CardValue.Five)
        {
            _handValue =+5;
        }
        else if (_cardsInHand[index].Value == CardValue.Six)
        {
            _handValue =+6;
        }
        else if (_cardsInHand[index].Value == CardValue.Seven)
        {
            _handValue =+7;
        }
        else if (_cardsInHand[index].Value == CardValue.Eight)
        {
            _handValue =+8;
        }
        else if (_cardsInHand[index].Value == CardValue.Nine)
        {
            _handValue =+9;
        }
        else if (_cardsInHand[index].Value == CardValue.Queen)
        {
            _handValue =+10;
        }
        else if (_cardsInHand[index].Value == CardValue.King)
        {
            _handValue =+10;
        }
        else if (_cardsInHand[index].Value == CardValue.Jack)
        {
            _handValue =+10;
        }
        else if (_cardsInHand[index].Value == CardValue.Ace)
        {
            if ((_handValue + 11) > 21)
            {
                _handValue =+1;
            }
            else
            {
                _handValue =+11;
            }
        }
    }
    #endregion
}

public enum HandRating
{
  BlackJack,
  TripleSeven,
  Busted,
  None,
}

Solution

  • There are a couple of things that needed to be changed in order to get the code to work:

    In the Hand class, HandValue and HandRating both have setters which does nothing, and should be refactored to be:

    public int HandValue { get; private set; }
    public HandRating HandRating { get; private set; }
    

    At the same time, remove the _handValue and _handRating fields as it's not necessary, and replace with the properties above.

    In CalculateHandValue(), there's a bug which introduces an IndexOutOfRange exception (the <= in the for loop should be <). CalculateHandValue() can be refactored to make use of a foreach loop, like below:

    private void CalculateHandValue()
    {
        foreach (var card in _cardsInHand)
        {
            ReturnValue(card);
        }
    }
    

    ReturnValue() doesn't cover all the card values (for instance 7 which was the use case in your console. Also, the incrementing was done incorrectly (should be += 2 instead of = +2). This is what it will look like if we add the new use case and fix the increment:

    private void ReturnValue(ICard card)
    {
        if (card.Value == CardValue.Two)
        {
            HandValue += 2;
        }
        else if (card.Value == CardValue.Three)
        {
            HandValue += 3;
        }
        else if (card.Value == CardValue.Four)
        {
            HandValue += 4;
        }
        else if (card.Value == CardValue.Seven)
        {
            HandValue += 7;
        }
    }
    

    I'll leave it up to you as an exercise to fill in the rest of the hand values, and maybe look into converting it into a switch statement.

    Create a new method CalculateHandRating() which will use most of the logic from the HandRating setter, but with modifications to ensure no no IndexOutOfRangeException happens:

    private void CalculateHandRating()
    {
        //TripleSeven
        if (_cardsInHand.Count == 3 &&
            _cardsInHand[0].Value == CardValue.Seven &&
            _cardsInHand[1].Value == CardValue.Seven &&
            _cardsInHand[2].Value == CardValue.Seven)
        {
            HandRating = HandRating.TripleSeven;
    
        }
        //BlackJack
        else if (_cardsInHand.Count == 2 &&
                _cardsInHand[0].Value == CardValue.Jack &&
                    _cardsInHand[1].Value == CardValue.Ace)
        {
            HandRating = HandRating.BlackJack;
        }
        //Busted
        else if (HandValue > 21)
        {
            HandRating = HandRating.Busted;
        }
        //None      
        else
        {
            HandRating = HandRating.None;
        }
    }
    

    Note the _cardsInHand.Count clauses at each if block to ensure we have the correct number of cards in hand before evaluating.

    Finally, in AddCard, add the following like so:

    public void AddCard(ICard card)
    {
        _cardsInHand.Add(card);
        CalculateHandValue();
        CalculateHandRating();
    }
    

    The class should look like this:

    public class Hand
    {
        private List<ICard> _cardsInHand = new List<ICard>();
    
        public int HandValue { get; private set; }
        public HandRating HandRating { get; private set; }
    
        public IEnumerable<ICard> CardsInHand
        {
            get
            {
                return _cardsInHand;
            }
        }
    
        public void CardsInHandConsole()
        {
            foreach (ICard card in _cardsInHand)
            {
                Console.WriteLine(card.ToString());
            }
        }
    
        public void AddCard(ICard card)
        {
            _cardsInHand.Add(card);
            CalculateHandValue();
            CalculateHandRating();
        }
    
        public void ClearHand()
        {
            _cardsInHand.Clear();
            HandValue = 0;
            HandRating = HandRating.None;
        }
    
        private void CalculateHandValue()
        {
            foreach (var card in _cardsInHand)
            {
                ReturnValue(card);
            }
        }
    
        private void CalculateHandRating()
        {
            //TripleSeven
            if (_cardsInHand.Count == 3 &&
                _cardsInHand[0].Value == CardValue.Seven &&
                _cardsInHand[1].Value == CardValue.Seven &&
                _cardsInHand[2].Value == CardValue.Seven)
            {
                HandRating = HandRating.TripleSeven;
    
            }
            //BlackJack
            else if (_cardsInHand.Count == 2 &&
                    _cardsInHand[0].Value == CardValue.Jack &&
                        _cardsInHand[1].Value == CardValue.Ace)
            {
                HandRating = HandRating.BlackJack;
            }
            //Busted
            else if (HandValue > 21)
            {
                HandRating = HandRating.Busted;
            }
            //None      
            else
            {
                HandRating = HandRating.None;
            }
        }
    
        private void ReturnValue(ICard card)
        {
            if (card.Value == CardValue.Two)
            {
                HandValue += 2;
            }
            else if (card.Value == CardValue.Three)
            {
                HandValue += 3;
            }
            else if (card.Value == CardValue.Four)
            {
                HandValue += 4;
            }
            else if (card.Value == CardValue.Seven)
            {
                HandValue += 7;
            }
        }
    }