1

My calculation is not working properly. I can not see anything wrong with the code. Sometimes it does not calculate the score properly. Sometimes it does perfectly. I can not even understand when it does properly and when it does not do it properly.

Score calculation should be like this:

Ace can add to the total score either 1 or 11. If the score is higher than 21, then ace is calculated as 1; otherwise ace is 11.

Here is my code:

  // Updates the the value of the cards the player has in their hand
  int updateValueOfHand() {
    int result = 0;                             // it will be returned
    int ace = 0;                                // value of ace

    for (int i =0; i < playerHand.size(); i++)  // loop to see players hand
    {
      int cardValue;                            // card value of hand
      Card card=(Card)playerHand.get(i);        // check the card
      cardValue = card.getRank();
      if (cardValue == 1)                       // if card value is 1 (ace)
      {
        cardValue = 0;                         // assign to 0
        ace += 1;                              // ace is 1 (if there are 2 aces ace is 2 ...)
      }
      result = result + cardValue;             // result is card value (no ace)
    }
    //return result;
    println("Number of ace: " + ace);
    if (ace!=0)                                //if there is ace
    {
      for (int j=0; j<ace; j++)                // if there is more than 1 ace
      {
        if (result+11<=21) {                   // if result is <= 21 when you count ace as 11, then ace is 11
          result+=11;
        }        
        else {
          result+=1;                          // otherwise ace is 1
        }        
      }
    }
    return result;
  }

enter image description here

gary
  • 4,227
  • 3
  • 31
  • 58
eMRe
  • 3,097
  • 5
  • 34
  • 51
  • Tip: if `playerHand` only holds `Card`s you should do `List` (or whatever List subclass you're using) ` = new List ();` That way you don't have to cast. – A--C Dec 24 '12 at 05:17

5 Answers5

6

Consider a hand with one King and two Aces. This should be calculated as 10 + 1 + 1, since otherwise it would be greater than 21.

However, the program loops through each Ace, and:

// if result is <= 21 when you count ace as 11, then ace is 11

Since the King plus the first Ace counted as 11 is <= 21, the program chooses to count the first Ace as 11, but this in incorrect.

Here is one idea to fix it: In your first for loop, increase result by 1 for every Ace, then in your second for loop, increase result by 10 for every Ace as long as it stays <= 21.

Joe Daley
  • 45,356
  • 15
  • 65
  • 64
  • In your first for loop, change `cardValue = 0;` to `cardValue = 1;`. In your second for loop, change the two `11`s to `10`s, and change `result+=1;` to `result+=0;`. If you get it working with those changes, you'll notice some of those lines do not actually do anything any more, and can be deleted. – Joe Daley Dec 24 '12 at 05:41
  • thanks a lot it works. but how can i test this to make sure it will work for all possibilities? – eMRe Dec 24 '12 at 05:45
  • There is a more advanced technique called 'unit testing' you can use to test a piece of code for many possibile inputs. In the most basic form, you could make a small, separate program with the above code in it (no GUI) and a main method that just calls the score calculation code over and over again with different hands and displays the output. It makes for a quick way to check your code's output for different inputs. – Joe Daley Dec 24 '12 at 05:55
2

Is there an elegant way to deal with the Ace in Blackjack?

Just treat each ace as 11. If your value is over 21, go through and foreach ace in your hand, subtract 10 from your total until either your score is 21 or less or you've gone through each ace. This will be your final score.

Community
  • 1
  • 1
2

For me the best way to do this is to get 2 totals:

  • The total of the hand (considering 11 for ace)
  • The total number of aces in the hand.

Then if hand_total > 21 subtract 10 from the hand_total for every ace until <= 21
An ace should always be counted as 11 unless it NEEDS to be 1 to prevent a bust.

TLama
  • 75,147
  • 17
  • 214
  • 392
tgwaste
  • 439
  • 3
  • 7
2

Here's my attempt

public int handScore(Hand hand)
{
    int score = 0;
    int aceCount = 0;
    for (Card card : hand.getCards())
    {
        switch (Card.RANK_SYMBOLS[card.getRank()])
        {
            case "2": score += 2; break; 
            case "3": score += 3; break;
            case "4": score += 4; break;
            case "5": score += 5; break;
            case "6": score += 6; break;
            case "7": score += 7; break;
            case "8": score += 8; break;
            case "9": score += 9; break;
            case "10":
            case "j":
            case "q":
            case "k": score += 10; break;
            case "a": score += 11; aceCount++; break;
        }

        while(score>21 && (aceCount-->=0))
            score -= 10;

    }
    return score; 
}
Ghandhikus
  • 839
  • 2
  • 9
  • 12
0

Here's .NET code I'm using, where Hand is a specialized collection of my Cards... anyways, you still get the basic idea and should be able to easily convert syntax and naming-conventions to Java.

protected int EvaluateHand(Hand hand)
    {
        int score = 0;
        foreach (Card currentCard in hand)
        {
            switch (currentCard.Value)
            {
                case Value.Two:
                    score += 2;
                    break; 
                case Value.Three:
                    score += 3;
                    break;
                case Value.Four:
                    score += 4;
                    break;
                case Value.Five:
                    score += 5;
                    break;
                case Value.Six:
                    score += 6;
                    break;
                case Value.Seven:
                    score += 7;
                    break;
                case Value.Eight:
                    score += 8;
                    break;
                case Value.Nine:
                    score += 9;
                    break;
                case Value.Ten:
                case Value.Jack:
                case Value.Queen:
                case Value.King:
                    score += 10;
                    break;
                case Value.Ace:
                    score += 11;
                    break; 

            }

        }

        // after evaluating with 11 for each ace, if score has busted, then change each ace value from 11 to 1
        if (score > 21)
        {   // if our evaluated score is over 21, subtract 10 foreach ace in the hand. 
            foreach (Card currentAceCheckCard in hand)
            {
                if (score <= 21)
                {   // if we've subtracted enough until we're not busted, then break and return value
                    break;
                }
                if (currentAceCheckCard.Value == Value.Ace)
                {
                    score -= 10;
                }
            }
        }
        return score; 
    }