我一直在做德州扑克游戏,作为评估的一部分,并且我一直在思考如何检查7张可用的卡并确定是否存在手牌。
我能想到的唯一可能的方法是对卡片进行数字排序,然后检查每组5张卡片,并检查它们是否与每只可能的手的列表匹配。这将花费很长时间,这将仅适用于确定对,因为该诉讼是无关紧要的。
这些牌都是由数字/ a / j / q / k和一套西装(char)3
(用小黑桃符号表示)组成的字符串。
有没有人有任何建议,公式或链接可用来帮助创建手部分析系统?
不必担心彼此之间排名靠前,那是另一回事。
我一直在做德州扑克游戏,作为评估的一部分,并且我一直在思考如何检查7张可用的卡并确定是否存在手牌。
我能想到的唯一可能的方法是对卡片进行数字排序,然后检查每组5张卡片,并检查它们是否与每只可能的手的列表匹配。这将花费很长时间,这将仅适用于确定对,因为该诉讼是无关紧要的。
这些牌都是由数字/ a / j / q / k和一套西装(char)3
(用小黑桃符号表示)组成的字符串。
有没有人有任何建议,公式或链接可用来帮助创建手部分析系统?
不必担心彼此之间排名靠前,那是另一回事。
Answers:
我认为您可以通过简单地对几张牌桌来找到大多数扑克手,每张牌中有多少张牌各具不同的花色。
换句话说,创建一个数组映射卡等级(数字和A / J / Q / K)到您手中该等级的卡数。如果玩家有一对或三个同类,则此数组中将有一个元素等于2或3,以此类推。如果有一个元素为2,另一个为3,则他们拥有一个满屋子。如果此数组中有五个等于1的连续元素。
同样,您可以对每套西服的牌数进行相似的排列,并使用它来检测同花。
一旦检测到特定手牌的存在,就很容易返回并找到该手牌中的特定牌,以便在UI或需要执行的操作中突出显示它们。
用伪代码:
int countByRank[13] = { 0 }; // Initialize counter to zero for each rank
for (cards in hand)
countByRank[card.rank] += 1; // Increment counter for this card's rank
if (countByRank.find(2))
// There's a pair
else if (countByRank.find(3))
// There's a three-of-a-kind
// etc...
这有点棘手,因为有很多组合。幸运的是,您拥有一个可以在很短的时间内检查大量组合的处理器。
您需要一些不同的策略来检测不同类型的手。幸运的是,一些不同的类型可以重叠策略。我会按手的顺序搜索。
2
,3
,6
,7
,8
都是简单的计数。使用从王牌到王牌的卡片列表,只需将每个值的编号放入列表中,对于找到的每张额外的卡片就递增。然后检查列表中是否有4,如果没有4,则说明您没有此类4。检查它是否为3s,如果没有3s,则说明您没有此类3。如果您有3,请检查2(表示满座)。等等...
对于1
,5
您可以使用相同的列表并查找序列,其中所有卡在列表中对于5张卡的序列都具有一个或多个条目。如果他们也有同样的衣服,那就是同花顺。
4
可以具有相同的列表设置,但是这次您要数衣服。寻找5或更高的数字。
最后,9
您拥有最高的卡,只需简单地查看上面列出的其中一个的最后一个最高值即可。
如果您按顺序搜索,找到匹配项后即可进行分类。如果要向用户提供所有信息,继续搜索并找到所有匹配项将是微不足道的。
本质上,您正在填充水桶。然后检查存储桶中的组合。为了显示:
从一个数组开始,每个卡都有一个存储桶,然后遍历卡并计算每个卡的实例。然后,您可以轻松地迭代数组并检查某些组合。在此示例中,很明显有一种类型为4,因为其中一个存储桶中有4个项目。
我曾经碰到过这种算法。它乘以质数来确定手,这是非常有趣的阅读。Cactus Kev的扑克手牌评估师
为了补充这个问题已经获得的出色答案,我认为一旦基本分类技术就位,提供一种最简单的手比较方法将很有帮助。首先,正如许多答案所建议的那样,您需要在手的类上标记手-您的大多数比较是“手X是否比手Y好?” 然后可以通过比较两只手的类别并查看哪个类别更好来完成。对于其余部分,您实际上需要逐个卡片进行比较,事实证明,进行更多分类工作会使此操作变得容易。
作为基准情况,请考虑两只手都是“高牌”手的情况;在这种情况下,您将首先比较两个最高的牌,然后比较(如果匹配)接下来的两张牌,依此类推。如果您假设每个输入手从最高牌到最低牌进行排序,则此方法将导致代码看起来像这个:
int CompareHandsOfSameClass(Hand h1, Hand h2) {
for ( int i = 0; i < 5; i++ ) {
if ( h1[i].rank > h2[i].rank ) {
return -1;
} else if ( h1[i].rank < h2[i].rank ) {
return 1;
}
}
return 0;
}
现在,这是个好消息:事实证明,此字典顺序已适当调整,可用于比较两个任意位置的类别,只要它们的类别相同即可。例如,由于比较对的方式是先比较对,然后再比较其他三张牌,因此您可以排序以将对放在第一(甚至是对中的一张!)并进行相同的比较。(因此,例如,将A9772之类的手存储为77A92或更好的是7A927;该手A9972将存储为9A729,并与上述代码进行比较,首先将7与9并置,然后发现A9972赢得)。两对手将被存储,两对中的较高者首先被存储,然后是较低的,然后是“踢球者”(例如,A9977将被存储为97A97)。一种类型的三张将与三张卡中的一张卡一起存储,然后是踢脚卡,然后是其他卡(例如,A7772为7A277);一个满满的房子将被存储着它的三个之一,然后是它的两个之一(例如,99777将被存储为79779);顺子和同花都可以按“直接词典顺序”存储,因为它们的比较就像高手牌一样。这导致了一个直接的外部比较器函数,该函数可通过已给定的函数适用于所有类别的手:
// Compare two hands, returning -1/0/+1 as hand 1 is less than, equal to,
// or greater than hand 2. Note that this function assumes the hands have
// already been classified and sorted!
int CompareHands(Hand h1, Hand h2) {
if ( h1.handClass > h2.handClass ) {
return -1;
} else if ( h1.handClass < h2.handClass ) {
return 1;
} else {
return CompareHandsOfSameClass(h1, h2);
}
}
希望这会有所帮助!
使用合适的卡表示形式和位旋转可以进行一些并行化。例如,此Java代码评估返回一张整数的7卡硬牌,该整数可用于比较两只手。它可以适用于以更用户友好的方式报告手的类型。核心思想来自于Cactus Kev在早期答案中引用的页面。
如果您仅对可能以各种语言命名手的实现感兴趣,而不是对效率和代码清晰度感兴趣,还可以 在codegolf.SE上查看“为扑克手命名”挑战。
首先,您需要知道所有牌的等级和适合度;琐碎但必要的。
然后,旋转这7张卡片并创建两个直方图;一个按等级(使用包含13个索引的数组,如果在发现具有该等级的手牌时将所有索引初始化为零,并递增1),另一个则一个(使用与等级相似构造的四个元素组成的数组) 。这些是线性运算,您只能为一组遍历对每张卡进行两种运算。
然后,您可以通过简单地检查每个直方图是否存在符合条件的存储桶和/或简单的后续测试来确定是否存在以下任何手:
您自然可以合并以下几种检查:
基本上,如果这些答案的答案出了任何手,则将所得的“手强度”值设置为找到的手的强度(如果该值尚未更高)。例如,如果您有一个满屋子,强度为7,强度为9,那么您也有一个强度为3的三个,强度为2,一对。
有几个快捷键和快速出局,但总体来说它不是真的是昂贵的只是运行所有的检查。
您可以使用简单的迭代方法相对轻松地进行扑克操作。
对于每张卡,请检查是否有一个或两个或三个其他人的同一张脸,以检查一对还是三张/四张同一种。
满屋都是相似的。或者,如果您发现一对和三个都不相同,则标记为已满。
对于同花顺,请检查每套衣服,看是否有五套相同的衣服。
进行直接检查很容易,即使未排序也是如此。对于每张卡,请检查是否有更高的卡,然后重复直到找到五张连续的卡。
皇家同花顺和同花顺与同花顺相似。皇家同花顺有一些额外的条件,那就是较低价值的卡可以忽略。
是的,这种方法效率不高,但是对于大多数扑克游戏而言,这是无关紧要的。您每半分钟左右检查一小撮玩家,而不是每秒检查数千手。
存在更好的方法,但是可能需要花费更多的时间进行编码,并且您可能有更多重要的事情要花时间/金钱,从算法的角度来看,除了算法的灵巧性和效率之外,这将使更好的游戏成为可能。
查找对子,双人对,toaks,满满的房子,扑克等的简单方法如下:
在这样的嵌套循环中将每个卡彼此比较:
int matches=0;
for (int i=0;i<5;i++)
for (int j=0;j<5;j++)
if (i!=j && cardvalue(card[j])==cardvalue(card[i])) matches++;
比赛将包含以下内容:
2对2
4对2对
6 6对局
8 对整场比赛
12对扑克
为了加快优化速度:不需要将j循环运行到5,可以将其运行到i-1。然后可以删除比较“ i!= j”,然后将匹配值减半(1 =对,2 = 2对等)