一副纸牌的所有不重复组合
All non-repeating combinations of a deck of cards
我正在尝试编写一个扑克赔率计算器。它背后的想法是,它通过所有可能打出的纸牌组合来强制执行。
我目前的逻辑(为了便于阅读而精简)如下;
For i = 0 To unknownCards - 1
For j = 1 To 4
'pick suit
For k = 1 To 13
'pick number
'do other work here
Next
Next
Next
然而这是错误的。它只会按顺序遍历卡片。出于我的目的,卡片的顺序并不重要(例如,我不想分别处理 2、3、4 和 4、3、2),但重要的是我看到每一种可能的独特组合。我只是不知道该怎么做?任何帮助或建议都会很棒。
P.S。我在 VB.net
中这样做
评论澄清后:要暴力获取所有手牌的列表,我知道的最简单的方法是对牌施加顺序(例如按数字排序,然后是花色:标准是梅花 2低,黑桃 A 高)然后选择升序排列的手牌。这样即使顺序对您来说无关紧要,但对您的手牌进行排序可确保您有一种明确的方式来决定独特的手牌。
一个,简单易懂但不是最佳的方法是嵌套 5 个循环:第一张牌的整个牌组,然后通过遍历低于该牌的所有牌来选择第二张牌,依此类推在。 (实际上,您可以从一副牌的第五张开始选择第一张牌,即梅花 3 张,依此类推,但完成后确保每手有 5 张牌可能更容易。)
我选择的语言是Python;如果你想要完整的列表,我会列出 52 张卡片,或者更好的是只给卡片编号和使用范围;然后在列表中使用 itertools.product 5 次以上,只允许 card_1this question 了解其用法。对于迭代器,我会查看他们的文档代码并将其修改为仅允许递增的手。也许更有经验的编码人员可以建议最佳迭代器。
有 2,598,960 种可能的手牌。此代码通过暴力生成所有可能的手牌。只生成 52 张牌 指数 的组合比担心循环中的花色和等级更快/更容易/更好。正是@ElizabethSQGoodman 所说的,其中有 5 个嵌套循环,在我的例子中,每个循环的起点都比前一个高。
出于性能原因,我选择了一个字节来保存每张牌,并选择了一个结构来保存手牌。然后,稍后,您可以根据规则计算出每张牌是什么牌:前 13 张是梅花,接下来的 13 张是方块,等等(参见 getHumanReadableHand())。在那里您还可以定义 A 的高位或低位(但不能同时定义两者,抱歉!)。等级 (A, 2, 3, ..., J, Q, K) 由索引模 13 确定。花色由 13 的整数除法确定。
Module Module1
Sub Main()
Dim hands As New List(Of Hand)()
For c0 As SByte = 0 To 51
For c1 As SByte = c0 + 1 To 51
For c2 As SByte = c1 + 1 To 51
For c3 As SByte = c2 + 1 To 51
For c4 As SByte = c3 + 1 To 51
Dim hand = New Hand
hand.Card0 = c0
hand.Card1 = c1
hand.Card2 = c2
hand.Card3 = c3
hand.Card4 = c4
hands.Add(hand)
Next c4
Next c3
Next c2
Next c1
Next c0
Console.WriteLine("There are {0} possible hands.", hands.Count)
Dim rnd As New Random()
Dim r = rnd.Next(hands.Count - 1)
Console.WriteLine("Random hand: {0}", getHumanReadableHand(hands(r)))
Console.WriteLine("Value: {0}", getHandValue(hands(r)))
Console.ReadLine()
End Sub
Function getHumanReadableHand(hand As Hand) As String
Static suits = {"C", "D", "H", "S"}
Static ranks = {"A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"}
Return String.Join(", ", hand.Cards.Select(Function(card) ranks(rank(card)) & suits(suit(card))))
End Function
Private Function rank(card As SByte) As SByte
Return card Mod 13
End Function
Private Function suit(card As SByte) As SByte
Return CSByte(card \ 13)
End Function
Function getHandValue(hand As Hand) As String
Dim cards = hand.Cards
If cards.Select(Function(card) rank(card)).Max() - cards.Select(Function(card) rank(card)).Min() = 4 AndAlso
cards.Select(Function(card) rank(card)).Distinct().Count = 5 AndAlso
cards.Select(Function(card) suit(card)).Distinct().Count = 1 Then
Return "Straight Flush"
ElseIf cards.OrderBy(Function(card) rank(card)).Take(4).Select(Function(card) rank(card)).Distinct().Count = 1 OrElse
cards.OrderBy(Function(card) rank(card)).Skip(1).Take(4).Select(Function(card) rank(card)).Distinct().Count = 1 Then
Return "Four of a Kind"
ElseIf cards.Select(Function(card) rank(card)).Distinct().Count = 2 Then
Return "Full House"
ElseIf cards.Select(Function(card) suit(card)).Distinct().Count = 1 Then
Return "Flush"
ElseIf cards.Select(Function(card) rank(card)).Max() - cards.Select(Function(card) rank(card)).Min() = 4 AndAlso
cards.Select(Function(card) rank(card)).Distinct().Count = 5 Then
Return "Straight"
ElseIf cards.OrderBy(Function(card) rank(card)).Take(3).Select(Function(card) rank(card)).Distinct().Count = 1 OrElse
cards.OrderBy(Function(card) rank(card)).Skip(1).Take(3).Select(Function(card) rank(card)).Distinct().Count = 1 OrElse
cards.OrderBy(Function(card) rank(card)).Skip(2).Take(3).Select(Function(card) rank(card)).Distinct().Count = 1 Then
Return "Three of a Kind"
ElseIf cards.Select(Function(card) rank(card)).Distinct().Count = 3 Then
Return "Two Pairs"
ElseIf cards.Select(Function(card) rank(card)).Distinct().Count = 4 Then
Return "One Pair"
Else
Return "Garbage"
End If
End Function
Structure Hand
Public Property Card0 As SByte
Public Property Card1 As SByte
Public Property Card2 As SByte
Public Property Card3 As SByte
Public Property Card4 As SByte
Public ReadOnly Property Cards As IEnumerable(Of SByte)
Get
Return New List(Of SByte)({Card0, Card1, Card2, Card3, Card4})
End Get
End Property
End Structure
End Module
示例输出:
There are 2598960 possible hands.
Random hand: 2C, 5C, 2D, 5S, KS
Value: Two Pairs
此代码大约需要 60 毫秒才能在我的机器上生成所有可能的手牌。
我正在尝试编写一个扑克赔率计算器。它背后的想法是,它通过所有可能打出的纸牌组合来强制执行。
我目前的逻辑(为了便于阅读而精简)如下;
For i = 0 To unknownCards - 1
For j = 1 To 4
'pick suit
For k = 1 To 13
'pick number
'do other work here
Next
Next
Next
然而这是错误的。它只会按顺序遍历卡片。出于我的目的,卡片的顺序并不重要(例如,我不想分别处理 2、3、4 和 4、3、2),但重要的是我看到每一种可能的独特组合。我只是不知道该怎么做?任何帮助或建议都会很棒。
P.S。我在 VB.net
中这样做评论澄清后:要暴力获取所有手牌的列表,我知道的最简单的方法是对牌施加顺序(例如按数字排序,然后是花色:标准是梅花 2低,黑桃 A 高)然后选择升序排列的手牌。这样即使顺序对您来说无关紧要,但对您的手牌进行排序可确保您有一种明确的方式来决定独特的手牌。
一个,简单易懂但不是最佳的方法是嵌套 5 个循环:第一张牌的整个牌组,然后通过遍历低于该牌的所有牌来选择第二张牌,依此类推在。 (实际上,您可以从一副牌的第五张开始选择第一张牌,即梅花 3 张,依此类推,但完成后确保每手有 5 张牌可能更容易。)
我选择的语言是Python;如果你想要完整的列表,我会列出 52 张卡片,或者更好的是只给卡片编号和使用范围;然后在列表中使用 itertools.product 5 次以上,只允许 card_1
有 2,598,960 种可能的手牌。此代码通过暴力生成所有可能的手牌。只生成 52 张牌 指数 的组合比担心循环中的花色和等级更快/更容易/更好。正是@ElizabethSQGoodman 所说的,其中有 5 个嵌套循环,在我的例子中,每个循环的起点都比前一个高。
出于性能原因,我选择了一个字节来保存每张牌,并选择了一个结构来保存手牌。然后,稍后,您可以根据规则计算出每张牌是什么牌:前 13 张是梅花,接下来的 13 张是方块,等等(参见 getHumanReadableHand())。在那里您还可以定义 A 的高位或低位(但不能同时定义两者,抱歉!)。等级 (A, 2, 3, ..., J, Q, K) 由索引模 13 确定。花色由 13 的整数除法确定。
Module Module1
Sub Main()
Dim hands As New List(Of Hand)()
For c0 As SByte = 0 To 51
For c1 As SByte = c0 + 1 To 51
For c2 As SByte = c1 + 1 To 51
For c3 As SByte = c2 + 1 To 51
For c4 As SByte = c3 + 1 To 51
Dim hand = New Hand
hand.Card0 = c0
hand.Card1 = c1
hand.Card2 = c2
hand.Card3 = c3
hand.Card4 = c4
hands.Add(hand)
Next c4
Next c3
Next c2
Next c1
Next c0
Console.WriteLine("There are {0} possible hands.", hands.Count)
Dim rnd As New Random()
Dim r = rnd.Next(hands.Count - 1)
Console.WriteLine("Random hand: {0}", getHumanReadableHand(hands(r)))
Console.WriteLine("Value: {0}", getHandValue(hands(r)))
Console.ReadLine()
End Sub
Function getHumanReadableHand(hand As Hand) As String
Static suits = {"C", "D", "H", "S"}
Static ranks = {"A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"}
Return String.Join(", ", hand.Cards.Select(Function(card) ranks(rank(card)) & suits(suit(card))))
End Function
Private Function rank(card As SByte) As SByte
Return card Mod 13
End Function
Private Function suit(card As SByte) As SByte
Return CSByte(card \ 13)
End Function
Function getHandValue(hand As Hand) As String
Dim cards = hand.Cards
If cards.Select(Function(card) rank(card)).Max() - cards.Select(Function(card) rank(card)).Min() = 4 AndAlso
cards.Select(Function(card) rank(card)).Distinct().Count = 5 AndAlso
cards.Select(Function(card) suit(card)).Distinct().Count = 1 Then
Return "Straight Flush"
ElseIf cards.OrderBy(Function(card) rank(card)).Take(4).Select(Function(card) rank(card)).Distinct().Count = 1 OrElse
cards.OrderBy(Function(card) rank(card)).Skip(1).Take(4).Select(Function(card) rank(card)).Distinct().Count = 1 Then
Return "Four of a Kind"
ElseIf cards.Select(Function(card) rank(card)).Distinct().Count = 2 Then
Return "Full House"
ElseIf cards.Select(Function(card) suit(card)).Distinct().Count = 1 Then
Return "Flush"
ElseIf cards.Select(Function(card) rank(card)).Max() - cards.Select(Function(card) rank(card)).Min() = 4 AndAlso
cards.Select(Function(card) rank(card)).Distinct().Count = 5 Then
Return "Straight"
ElseIf cards.OrderBy(Function(card) rank(card)).Take(3).Select(Function(card) rank(card)).Distinct().Count = 1 OrElse
cards.OrderBy(Function(card) rank(card)).Skip(1).Take(3).Select(Function(card) rank(card)).Distinct().Count = 1 OrElse
cards.OrderBy(Function(card) rank(card)).Skip(2).Take(3).Select(Function(card) rank(card)).Distinct().Count = 1 Then
Return "Three of a Kind"
ElseIf cards.Select(Function(card) rank(card)).Distinct().Count = 3 Then
Return "Two Pairs"
ElseIf cards.Select(Function(card) rank(card)).Distinct().Count = 4 Then
Return "One Pair"
Else
Return "Garbage"
End If
End Function
Structure Hand
Public Property Card0 As SByte
Public Property Card1 As SByte
Public Property Card2 As SByte
Public Property Card3 As SByte
Public Property Card4 As SByte
Public ReadOnly Property Cards As IEnumerable(Of SByte)
Get
Return New List(Of SByte)({Card0, Card1, Card2, Card3, Card4})
End Get
End Property
End Structure
End Module
示例输出:
There are 2598960 possible hands.
Random hand: 2C, 5C, 2D, 5S, KS
Value: Two Pairs
此代码大约需要 60 毫秒才能在我的机器上生成所有可能的手牌。