Is there an elegant way to deal with the Ace in Bl

2019-01-15 07:15发布

问题:

My kiddo had a homework assignment to write Blackjack in Java. I helped him a little but for the most part he did it all himself and it actually plays pretty well. He even caught an error I didn't see in how it was calculating hand values. However, there is a snag that he hasn't dealt with and every solution I can think of is really complicated and way beyond what he's going to be able to easily code up with his still rudimentary Java skills.

The Ace. In fact, not just one Ace, there's four of them and you could possibly get all four of them in a single hand. How do you elegantly deal with calculating the value of a hand of cards when there's one or more Aces, each of which might be valued at one or eleven. I feel like there should be a graceful algorithm for it, but I'm not seeing it. Of course, part of it could just be that I'm tired, but maybe you can help.

回答1:

Just treat each ace as 11. Then while the value is over 21, subtract 10 from your total for each ace in your hand.



回答2:

You will only ever use 1 ace for the 11 points. So calculate all but the last ace as 1 and if have 10 or less points, the last ace counts as 10.



回答3:

Only 1 Ace ever counts as 11.

So, an alternative method to treating each Ace as 11 would be to treat every Ace as 1. Then add 10 to the total value ( carried regardless of Ace on hand ) and keep that in a separate "high" variable ( value + 10 ). Also create a boolean of ~ ace:true if (any) ace comes up.

And so when checking the score against the dealer; check if the players' hand has (any) Ace, in which case you ( can ) use the "high" value, otherwise ( no Ace ) use the "low" value.

That way King + 9 + Ace ( bad example perhaps ) would be ~ low:20 & high:30 & ace:true - With that information you can check if 30 - 10 will "win the game". So, King + 5 + 5 ( low:20 high:30 ace:false ) will not use it's high value of 30.

I'm using this method so I know when to show an alt. Ace score onscreen; like 3/13 ( Ace + 2 ), using the same ace:true|false boolean I already have. This is surely the same answer as the first one given, but this makes more sense to me :)



回答4:

No matter what every ace should be counted to sum value as 11, then when the total sum has reached over 21 subtract 10 from hand, but the thing is you must make sure you keep a count of how many times you subtract 10 and how many times you add 11( an ace),

add 11 >= subtract 10 -must always be satisfied

alorithm example:

int sum=0;
int ace=0;
int subtract=0;
while(!busted or !stay)
{
  Hitme(value);
  if(value=11)ace++;
  sum+=value;
  if(sum>21) 
  {
      if(ace>=1)
      {
         if(ace>=subtract)
         {
           sum-=10
           subtract++;
         }
         else
         {
            busted;
         }
      }
      else
      {
          busted;
      }
  }
  else
  {
    hit or stay;
    //of course if sum== 21 then force stay

  }
}


回答5:

Similar to elundmark's answer...

You've most likely got a method that evaluates a blackjack hand value. Always value aces at one point. If a hand contains an ace, compute a hard value (all aces are ones, +10) and a soft value (all aces ones).

If the hard value is not a bust, return the hard value. If the hard value is a bust, return the soft value.

example 1
2, A, A
hard value 2 + 1 + 1 + 10 = 14
soft value = 2 + 1 + 1 = 4

hard value < 21, so return hard value (hand value is 14)

example 2
2, A, A, 8
hard value = 2 + 1 + 1 + 8 + 10 = 22 (bust)
soft value = 2 + 1 + 1 + 8 = 12

hard value > 21, so return soft value (hand value is 12)

Traditional thinking about the rules and the way the game is played, is that an Ace's value is conditional and can have two values, 1 or 11. This concept is difficult to implement. It's much easier on a programmer to count all Aces as a value of one and conditionally add 10 points to the hand value. That way your Card's Rank or Value implementation can remain rigid and straightforward. I've experimented with this before by returning a collection of values and a couple other methods. It's a pain, and not worth it for just the one Ace rank.

If you want to show an alt on the screen like 2/12, instead of returning an Integer, just return a "BlackjackValue" object that contains an Integer and a String object that you create in the method that evaluates your hand value.



回答6:

short aces_count = 0;
short non_aces_sum = 0;
short global_sum = 0;

foreach card in _card:{
    if( card.value != 11 ){ // assuming ace value is 11
        if( card.value > 10 ) 
            non_aces_sum += 10;
        else
            non_aces_sum += card.value
    }else
        aces_count += 1;
}

short aces_sum = 0;
if( aces_count > 0) aces_sum = 11;

for(int i=0 ; i < aces_count - 1; i++){ // - 1 cuz already asigned first ace
    aces_sum += 1; // 2x aces == 22 so max 1 ace has value 11
}
if(aces_sum + non_aces_sum > 21)
    aces_sum = aces_count; // no need for an 11 value ace, so all are 1

global_sum = non_aces_sum + aces_sum;


回答7:

The problem is that it's not determined: you can count (as I understand the rules) an Ace as either 1 or 11. But you know you're not going to count it as 11 every time, because you'll bust.

The only solution I think is to compute the score for each possible value of the ace where the sum <= 21.