15

我的孩子有一个家庭作业是用 Java 编写 Blackjack。我帮助了他一点,但大部分都是他自己做的,而且实际上打得很好。他甚至在计算手牌价值时发现了一个我没有看到的错误。然而,有一个他没有处理过的问题,而且我能想到的每一个解决方案都非常复杂,远远超出了他能够用他仍然初级的 Java 技能轻松编写代码的能力。

王牌。事实上,不仅仅是一张 A,还有四张 A,而且你可以在一手牌中拿到全部四张。当有一个或多个 A 时,你如何优雅地计算一手牌的价值,每个 A 的价值可能为 1 或 11。我觉得应该有一个优雅的算法,但我没有看到它。当然,部分原因可能是我累了,但也许你可以帮忙。

4

7 回答 7

26

只需将每个 A 视为 11。然后当值超过 21 时,从您手中的每个 A 的总数中减去 10。

于 2009-05-08T02:15:43.863 回答
9

您将只使用 1 个 ace 来获得 11 分。因此,除最后一个 ace 以外的所有点都计算为 1,如果点数为 10 或更少,则最后一个 ace 计为 10。

于 2009-05-08T02:38:09.813 回答
5

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 :)

于 2010-09-16T22:13:25.977 回答
3

不管每个 ace 应该算什么总和为 11,然后当总和超过 21 时,从手上减去 10,但问题是你必须确保你记下你减去 10 的次数和多少次加 11(一张 ace)的次数,

加 11 >= 减 10 -必须始终满足

算法示例:

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

  }
}
于 2009-05-08T02:22:19.867 回答
2

类似于elundmark的回答......

您很可能有一种评估二十一点手牌价值的方法。始终在某一时刻重视 A。如果一手牌中有一张 A,计算一个硬值(所有 A 都是 1,+10)和一个软值(所有 A 都是)。

如果硬值不是半身像,则返回硬值。如果硬值是半身像,则返回软值。

示例 1
2, A, A
硬值 2 + 1 + 1 + 10 = 14
软值 = 2 + 1 + 1 = 4

hard value < 21, 所以返回 hard value (hand value 是 14)

例子 2
2, A, A, 8
硬值 = 2 + 1 + 1 + 8 + 10 = 22 (胸围)
软值 = 2 + 1 + 1 + 8 = 12

硬值 > 21,所以返回软值(手值是 12)

对规则和游戏方式的传统思考是,A 的值是有条件的,可以有两个值,1 或 11。这个概念很难实现。对于程序员来说,将所有 A 计为 1 并有条件地在手牌值上加 10 点要容易得多。这样,您的卡的等级或价值实施可以保持僵化和直接。我之前通过返回一组值和其他几种方法对此进行了试验。这是一种痛苦,不值得仅仅为了一个 Ace 等级。

如果您想在屏幕上显示一个 alt(如 2/12),而不是返回一个整数,只需返回一个“BlackjackValue”对象,其中包含一个整数和一个字符串对象,该对象是您在评估您的手牌价值的方法中创建的。

于 2012-10-17T20:16:58.463 回答
0
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;
于 2017-06-26T13:20:13.557 回答
-1

问题是它不是确定的:你可以将一张 A 算作 1 或 11(根据我的理解规则)。但你知道你不会每次都算作 11,因为你会破产。

我认为唯一的解决方案是计算总和 <= 21 的 ace 的每个可能值的分数。

于 2009-05-08T02:12:25.943 回答