计算二十一点中的手值

时间:2010-03-08 15:42:38

标签: c# blackjack

我在C#中实现了一个小Black Jack游戏,我在计算玩家的手牌值时遇到以下问题。根据玩家的手牌,A值可能为1或11。如果玩家有三张牌和一张牌,那么如果牌的总和<= 10,则牌的值为11,否则值为1.

现在让我们假设我不知道玩家获得了多少个游戏并且实施了游戏,这使得经销商可以使用多张牌。用户可以用一只手甚至5,6,7,8 ... aces。

最好的方式(可能使用Linq)评估玩家获得最接近21的所有a(除了其他牌之外)的最佳方式是什么?

我知道玩家的牌,我想计算他们的价值,使用A来达到最接近21的值。

5 个答案:

答案 0 :(得分:3)

看起来并不那么复杂,

  • 你只需添加所有其他牌并找到手牌的较低值
  • 现在你有两种情况:
    • sum <= 10:所以你检查假设一个ace可以被认为是11的两个结果:sum + 11 + (numAces-1)*1 <= 21,那么这是最接近21的值,否则sum + numAces*1(因为使用ace作为11会溢出)
    • sum > 10:您可以将Aces视为1,因此最终值为sum + numAces*1

(从未使用 C#所以这个答案是元代码)

答案 1 :(得分:2)

添加所有非a的值并添加a的数量:2,Q,A,A = 2 + 10 +(2)= 14

然后从21:21-14 = 7

减去

这个数字是否小于10(如果只有1个ace == 11)?少于20(如果两个A = = 11)?

因为这感觉就像家庭作业一样,故意不是完整的答案,而是应该引导你。

答案 2 :(得分:0)

如上所述,您应该能够使用Aggregate扩展方法实现此功能。编写一个实现算法的函数并使用它:

IEnumerable<int> cards = // card values
var f = (int i1, int i2) => // implement algorithm here
var result = cards.Aggregate(f);

答案 3 :(得分:0)

从我的角度来看,你必须考虑这样一个事实:当玩家有一个或多个A时,他或她在任何给定的时间都有两个可能的分数。试图计算最接近的单个值到21岁是对二十一点中持有王牌的意义的错误抽象。

作为一名玩家,我不希望程序告诉我,当我拥有ace&amp; 5,因为我可能不会打16,但如果我有ace&amp; 5我绝对会接受这个打击。从概念上讲,我确实有6个 16。

我认为手的价值应该可以表示为一个或两个值。显然,在没有王牌的情况下,只有一个值。同样地,当ace-as-eleven意味着被击败的手时,手牌只有一个值,因为ace 必须被计为1.你也可以说任何ace + 10组合只有一个值,因为那是即时二十一点。

这是一个部分实现 - 许多方法之一,皮肤这猫。我这样写它是为了让你以某种方式思考;因为只有a只能有一个以上的值而且给定的手最多可以有两个可能的值,所以这可以更简洁地完成。

public interface Hand
{
   IEnumerable<int> PossibleValues { get; set; }
}
public interface Card
{
   CardValues PossibleValues { get; set; }
}
public interface CardValues
{
    int Value1 { get; }
    int Value2 { get; }
}

public class BlackjackHand : Hand
{
    IList<Card> cards;

   public IEnumerable<int> PossibleValues
   {
        IList<int> possible_values = new List<int>();

        int initial_hand_value = cards.Sum(c => c.Value1);
        if(initial_hand_value <= 21)
        {
            possible_values.Add(initial_hand_value);
            yield return initial_hand_value;
        }

        foreach(Card card in cards.Where(c => c.Value2 > 0))
        {
            IList<int> new_possible_values = new List<int>();
            foreach(int value in possible_values)
            {
                var alternate_value = value + card.Value2;
                if(alternate_value <= 21) 
                {
                    new_possible_values.Add(alternate_value);
                    yield return alternate_value;
                }
            }
            possible_values.AddRange(new_possible_values);
        }

        yield break;
   }
}

答案 4 :(得分:0)

以这种方式考虑它可能是最简单的 - 每张牌都会将牌值加到总计数牌为11.如果牌是王牌,并且牌手被击败,则扣除10。 示例:

int total = 0;
...
int hit = GetHit();
total = total + hit;

if (total > 21 && hit == 11)
{
  total = total - 10
}
// check if player busted, etc

在您的初始交易中,您可以使用GetHit()“处理”这些卡片,或者自己动手处理Ace-Ace(只有2张卡片的问题情况)。这将始终为您提供最高的手。我认为可以认为球员知道一个ace可以是1或11,所以用Ace-5击球将永远不会让球员摔倒。