如何在纸牌绘图游戏中检测“手”

时间:2015-03-31 12:57:13

标签: c# algorithm probability

有一个数组代表一张完整牌组中的5张牌(52张牌) 所以随机手看起来像这样['H3','H6','D3','D4','S4'],(这里是h 2对4和3)。
我正在寻找一种方法来了解随机5张卡的这些属性:

  • 它的名字是什么。即:“四种”,“三种”等 上。
  • 那只手的概率是多少,请记住它是一只手 完美随机。
  • 我可以选择数据结构
  • 我用c#

3 个答案:

答案 0 :(得分:4)

一旦考虑到存在基于值的层次结构,识别手牌很容易。因此,虽然同花顺也是同花顺,而满屋也是两对,你总是会选择更有价值的分类。

这意味着如果您按照每个牌的标准按照值的降序检查五张牌,则第一张匹配将是正确的。 (像strategy pattern这样的东西在这里非常有用。)

至于概率,我只是look them up。 (请注意,完整的牌组是52张牌而不是54张。)

答案 1 :(得分:1)

关于拥有每只手的概率,这是一个简单的计数问题,考虑到有52个选择5 = 2,598,960个不同的牌,所以你只需要计算有多少手有资格获得每种类型的牌和除它由2598960。

例如,有4个不同的皇室冲洗 - >机会为4 / 2,598,960 = 0.000153907%

有4 * 10 = 40个不同的直接冲洗 - >机会为40 / 2,598,960 = 0.00153907%

有13 * 48 = 624个不同的四边形 - >机会为624 / 2,598,960 = 0.024009603%

等等..

如果您不喜欢计算问题,可以使用您的程序枚举这些2,598,960手并计算有多少次冲洗,四边形等。

关于检测手的代码 - 我会按排序顺序存储手(根据卡的等级/高度,忽略套装,即[' H3',' D3&# 39;,' D4'' S4'' H6'])。这将帮助您非常有效地检测对,两对,三胞胎,四边形,满屋和直道。 检测同花是非常容易的 - 只需检查所有五张牌是否来自同一套装。你完成了!

答案 2 :(得分:1)

首先设置一些数据结构来表示套装,等级,牌和手。有许多方法可以做到这一点以获得良好的性能,例如:使用位向量,但假设我们想让它可读:为套装和排名制作枚举,为卡片制作结构,为手制作类。顺便说一句,这种类型的例子就是你希望的using F#

注意:代码仅用于说明目的:它从未见过编译器。不要指望粘贴这个&跑。

enum Suit { Spades, Hearts, Diamonds, Clubs }
enum Rank { Two, Three, Four, Five, Six, Seven, 
            Eight, Nine, Ten, Jack, Queen, King, Ace }

enum HandType { Nothing, Pair, TwoPair, ThreeOfAKind, Straight,
     Flush, FullHouse, FourOfAKind, StraightFlush }    

public struct Card 
{
   public Suit Suit { get; private set; }
   public Rank Rank { get; private set; }
   public Card(Rank rank, Suit suit)
   {
      Suit = suit;
      Rank = rank;
   }     
}

public class Hand 
{
   public IReadOnlyList<Card> Cards { get; private set };
   public Hand(IEnumerable<Card> cards) 
   { 
      this.Cards = cards.OrderByDescending(c => c.Rank).ToList(); 
   }   
}

评估可以通过一种方法来完成,该方法可以牵手并返回手的种类。请注意,这只分类手牌,它实际上并没有计算出完整的等级,因此较高的直线击败较低等等。我遗漏了实际的实现,但这是一个骨架:

public static class HandEvaluator
{
    public static HandType GetHandType(Hand hand)
    {           
       bool isFlush = hand.Cards.Distinct(c => c.Suit).Count() == 1;
       bool isStraight = // five consecutive ranks. Mind the wheel straight Ace->5! 
       if (isStraight && isFlush)
         return HandType.StraightFlush;           

       // group cards by rank, then find the group count & sizes
       var groups = hand.Cards.GroupBy(c => c.Rank);

       if (/* max group size = 4 */)
          return HandType.FourOfAKind;
       if (/* two groups and max group size = 3 */)
          return HandType.FullHouse;
       if (isFlush)
         return HandType.Flush;
       if (isStraight)
         return HandType.Straight;   
       if (/* three groups and max group size 3 */)
          return HandType.ThreeOfAKind;

       // ... And so on for two pair, pair. 

       return HandType.Nothing;
    }
}

至于不同手的概率:你应该能够在纸上做的比用程序更容易,但是一旦你有了一个分类程序,你就可以通过生成所有可能的手,分类它们来轻松获得统计数据,以及通过评估的手型对结果进行分组/计数。