我在苦苦挣扎的写一个扑克评价图书馆的乐趣,并希望增加的能力测试用于绘制(开放的结束,内听顺子)对于给定一套卡片。

只是想知道什么是"国家的艺术"吗?我试图保持我的记忆中占合理的,这样的想法使用查对表不坐好,但可能是一种必要的邪恶。

我现在的计划是沿着线:

  • 减去最低的排名从排名的所有卡。
  • 看看如果某些序列,即:0、1、2、3或1、2、3、4的(对于OESDs)的子集修改的收集。

我希望能做的更好的复杂性,明智的,因为7卡或9卡组将研东西停止使用我的办法。

任何输入和/或更好的想法,将不胜感激。

有帮助吗?

解决方案

最快的方法可能是为每个卡等级分配一个位掩码(例如deuce= 1,三个= 2,四个= 4,五个= 8,六个= 16,七个= 32,八个= 64,九= 128,十= 256,千斤顶= 512,女王/王后= 1024,国王= 2048,王牌= 4096),或对所有手牌的掩码值进行或运算。然后使用8192个元素的查找表来指示该手牌是直牌,张开牌,直击还是无意义(其中也可以包括各种后门直牌,而不会影响执行时间)。

顺便说一句,使用不同的位掩码值,可以快速检测其他有用的手,例如两种,三种等。如果一个具有64位整数数学运算,请使用上面指示的位掩码(所以deuce= 1,三个= 8,依此类推,直到ace= 2 ^ 36),然后将卡的值相加。如果结果与04444444444444(八进制)加和为非零,则该手为四合一。否则,如果加正01111111111111,然后与04444444444444进行加和运算,得出的结果非零,则该手为三人或全满。否则,如果与02222222222222相加的结果不为零,则该手牌为一对或两对。要查看一手牌是否包含两对或更多对,请用02222222222222将“和”值“和”,然后保存该值。减去1,然后将结果与保存的值相加。如果不为零,则该手至少包含两对(因此,如果其中包含三类,则为满屋;否则为两对)。

另外,检查直线度的计算也将使您快速确定手牌有多少个不同等级。如果有N张牌和N个不同等级的牌,则该手牌不能包含任何对或更好的对(当然,可以包括同花或同花)。如果存在N-1个不同等级,则该手正好包含一对。只有在不同等级的人较少的情况下,才可以使用更复杂的逻辑(如果有N-2,则该手可以是两对或三种);如果N-3以下,则该手可以是“三对”(得分为两对),满员或同类四人。

另一件事:如果您无法管理8192元素的查找表,则可以使用512元素的查找表。如上计算位掩码,然后在array [bitmask&511]和array [bitmask >> 4]上进行查找,然后对结果进行“或”运算。任何合法的平局或平局都会在一个或其他查找中进行注册。请注意,这不会直接为您提供不同等级的数量(因为在两次查找中都会计算出六到十张卡片),但是对同一阵列再进行一次查找(使用array [bitmask >> 9])将仅计入千斤顶通过ace。

其他提示

我知道您说过要保持尽可能小的内存占用,但是有一种非常有效的内存查询表优化,我已经在一些扑克手评估器中看到过,我自己也使用过。如果您正在进行大量的扑克模拟并且需要最佳的性能,则可能要考虑这一点。尽管我承认在这种情况下差异并不大,因为测试顺子抽签并不是很昂贵的操作,但是相同的原理几乎可以用于扑克编程中的每种手型评估。

这个想法是我们创建一种具有以下属性的哈希函数:
1)为每组不同的纸牌等级计算一个唯一值
2)从某种意义上讲是对称的,它并不取决于卡的顺序
这样做的目的是减少查找表中所需的元素数量。

一种简洁的方法是为每个等级分配一个质数(2-> 2、3-> 3、4-> 5、5-> 7、6-> 11、7-> 13、8 -> 17、9-> 19,T-> 23,J-> 29,Q-> 31,K-> 37,A-> 41),然后计算素数的乘积。例如,如果卡片为39TJQQ,则哈希为36536259。

要创建查找表,您需要遍历所有可能的等级组合,并使用一些简单的算法来确定它们是否构成直线绘制。对于每种组合,您还需要计算哈希值,然后将结果存储在映射中,其中Key是哈希,而Value是直接抽签检查的结果。如果最大卡数很小(4张或更少),那么甚至线性阵列也是可行的。

要使用查找表,您首先需要计算特定卡片组的哈希值,然后从地图中读取相应的值。

这是C ++中的一个示例。我不保证它能正常工作,并且可以通过使用排序数组和二进制搜索而不是hash_map对其进行很多优化。 hash_map为此目的有点慢。 通用标签

这可能是一个幼稚的解决方案,但是我不确定性能方面的问题,尽管可以肯定,但我可以肯定它会起作用。

再次假设这些卡由数字1-13表示,那么如果您的4张卡的数字范围为3或4(从最高到最低卡级别),并且没有重复,那么您就有可能进行平局。

3的范围表示您有一个开放式抽奖,例如2,3,4,5的范围为3,不包含重复项。

4的范围表示您有一个固执己见(如您所说的),例如5,6,8,9的范围是4,并且没有重复项。

更新:每个基督教曼的评论...它可以是这样的:

让我们说, A 表示为 1. J 作为11, Q 12等。

loop through 1 to 13 as i
  if my cards already has this card i, then don't worry about this case, skip to next card
  for this card i, look to the left for number of consecutive cards there is
  same as above, but look to the right
  if count_left_consecutive + count_right_consecutive == 4, then found case

你会需要定义功能,以寻找最左连续的卡右连续的卡片...并且还处理这种情况,当时在寻找合适的连续,之后 K, , A 是连续的。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top