如何在抽卡游戏中检测"Hand"
How to detect "Hand" in a card drawing game
有一个数组代表从整副牌(52 张牌)中挑选出的 5 张牌。
所以一手随机的牌看起来像这样 ['H3','H6','D3','D4','S4'],(这里是 h 2 对 4 和 3) .
我正在寻找一种方法来了解随机 5 张卡片的属性:
- 是什么手牌。即:"Four of a kind"、"Three of a kind" 等等
上。
- 那手牌的概率是多少,考虑到它是
完美随机。
- 我可以选择数据结构
- 我用c#
一旦您考虑到存在基于值的层次结构,识别一手牌就很容易了。所以虽然同花顺也是同花顺,葫芦也是两对,但你总是会选择更有价值的分类。
这意味着如果您按照每手牌的价值降序检查您的五张牌,则第一张匹配将是正确的。 (像 strategy pattern 这样的东西在这里可能非常有用。)
至于概率,我只是look them up。 (请注意,一副完整的牌是 52 张而不是 54 张。)
关于每手牌的概率,这是一个简单的计数问题,考虑到有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 手牌并计算有多少次同花、四条等等。
关于检测手牌的代码——我会按排序顺序存储手牌(根据卡片的 rank/height,忽略花色,即 ['H3'、'D3' ,'D4','S4','H6'])。这将帮助您非常有效地检测对、两对、三胞胎、四胞胎、葫芦和顺子。
检测同花很容易 - 只需检查所有五张牌是否来自同一花色。大功告成!
首先设置一些数据结构来表示花色、点数、牌和手牌。有很多方法可以做到这一点以获得良好的性能,例如使用位向量,但假设我们想让它可读:为花色和等级制作枚举,为纸牌制作结构,为手牌制作 class。顺便说一下,这种类型的示例正是您希望的地方 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();
}
}
评估可以用一种方法来完成,该方法接受一只手和 returns 一只手的种类。请注意,这只是 class 确定 这手牌,它实际上并没有计算出完整的排名,例如较高的顺子击败较低的顺子等等。我省略了实际的实现,但这里有一个框架:
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;
}
}
至于不同手牌的概率:那些你应该能够在纸上做的比用程序更容易,但是一旦你有一个 classifying 程序,你可以通过生成所有可能的手,class 化它们,grouping/counting 评估手型的结果。
有一个数组代表从整副牌(52 张牌)中挑选出的 5 张牌。
所以一手随机的牌看起来像这样 ['H3','H6','D3','D4','S4'],(这里是 h 2 对 4 和 3) .
我正在寻找一种方法来了解随机 5 张卡片的属性:
- 是什么手牌。即:"Four of a kind"、"Three of a kind" 等等 上。
- 那手牌的概率是多少,考虑到它是 完美随机。
- 我可以选择数据结构
- 我用c#
一旦您考虑到存在基于值的层次结构,识别一手牌就很容易了。所以虽然同花顺也是同花顺,葫芦也是两对,但你总是会选择更有价值的分类。
这意味着如果您按照每手牌的价值降序检查您的五张牌,则第一张匹配将是正确的。 (像 strategy pattern 这样的东西在这里可能非常有用。)
至于概率,我只是look them up。 (请注意,一副完整的牌是 52 张而不是 54 张。)
关于每手牌的概率,这是一个简单的计数问题,考虑到有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 手牌并计算有多少次同花、四条等等。
关于检测手牌的代码——我会按排序顺序存储手牌(根据卡片的 rank/height,忽略花色,即 ['H3'、'D3' ,'D4','S4','H6'])。这将帮助您非常有效地检测对、两对、三胞胎、四胞胎、葫芦和顺子。 检测同花很容易 - 只需检查所有五张牌是否来自同一花色。大功告成!
首先设置一些数据结构来表示花色、点数、牌和手牌。有很多方法可以做到这一点以获得良好的性能,例如使用位向量,但假设我们想让它可读:为花色和等级制作枚举,为纸牌制作结构,为手牌制作 class。顺便说一下,这种类型的示例正是您希望的地方 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();
}
}
评估可以用一种方法来完成,该方法接受一只手和 returns 一只手的种类。请注意,这只是 class 确定 这手牌,它实际上并没有计算出完整的排名,例如较高的顺子击败较低的顺子等等。我省略了实际的实现,但这里有一个框架:
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;
}
}
至于不同手牌的概率:那些你应该能够在纸上做的比用程序更容易,但是一旦你有一个 classifying 程序,你可以通过生成所有可能的手,class 化它们,grouping/counting 评估手型的结果。