检查扑克直
Check for poker straight
我已经成功地创建了一个算法来检查一手牌的排名。它 100% 正确地工作,但速度很慢。我一直在分析代码,check straight 函数是其中最慢的部分之一。
所以我的问题是,有没有更好的方法来计算一手牌是否顺子?
这里有一些细节:
7 张牌,持有人 2 张,牌面 5 张。 A 可高可低。
每张卡片都分配了一个值:
2 = 2
3 = 3
..
9 = 9
T = 10
J = 11
问 = 12
K = 13
A = 14
该脚本包含所有 7 张卡片的数组:
$cards = array(12,5,6,7,4,11,3);
所以现在我需要能够将其排序到一个数组中:
- 丢弃重复项
- 卡片从低到高排序
- 只有 returns 5 张连续的牌,即(3,4,5,6,7)
要快;循环和迭代非常昂贵。这是我目前使用的,当它试图分析 15000 手牌时,它会对脚本造成影响。
对于以上,我使用了:
- 丢弃重复项(使用array_unique)
- 从低到高排序卡片(使用 sort())
- 只有return 5张连续的卡片(使用for循环检查卡片的值)
有没有人有任何我可以改进的例子?甚至可以用另一种语言,我也许可以看看它是如何完成的?
与其使用数组重复数据删除和排序,不如考虑使用位掩码,并将设置卡值的位设置为 1。位掩码的工作方式类似于 Set 数据结构,并且在检测连续元素时具有额外的优势。
for ($i = 0; $i < count($cards); $i++) {
$card = $cards[$i];
// For each card value, set the bit
if ($card == 14) {
// If card is an ace, also set bit 1 for wheel
$cardBitmask |= 0x2;
}
$cardBitmask |= (1 << $card);
}
// To compare, you simply write a for loop checking for 5 consecutive bits
for($i = 10; $i > 0; $i--)
{
if ($cardBitmask & (0x1F << $i) == (0x1F << $i)) {
// Straight $i high was found!
}
}
考虑 this link 的 Java 实施。我把它放在这里了:
public static boolean isStraight( Card[] h )
{
int i, testRank;
if ( h.length != 5 )
return(false);
sortByRank(h); // Sort the poker hand by the rank of each card
/* ===========================
Check if hand has an Ace
=========================== */
if ( h[4].rank() == 14 )
{
/* =================================
Check straight using an Ace
================================= */
boolean a = h[0].rank() == 2 && h[1].rank() == 3 &&
h[2].rank() == 4 && h[3].rank() == 5 ;
boolean b = h[0].rank() == 10 && h[1].rank() == 11 &&
h[2].rank() == 12 && h[3].rank() == 13 ;
return ( a || b );
}
else
{
/* ===========================================
General case: check for increasing values
=========================================== */
testRank = h[0].rank() + 1;
for ( i = 1; i < 5; i++ )
{
if ( h[i].rank() != testRank )
return(false); // Straight failed...
testRank++; // Next card in hand
}
return(true); // Straight found !
}
}
快速 Google 搜索 "check for poker straight (desired_lang)
" 将为您提供其他实现。
你可以这样走,你不需要排序或任何东西(假设2是2,14是ace):
$cards = [12,5,6,7,4,11,3];
function _inc(&$i) {
if ($i == 14)
$i = 2;
else
$i++;
return $i;
}
$straight = false;
for($i = 2; $i <= 14; $i++) {
$ind = $i;
if (!in_array($ind, $cards)) continue;
$s = [$ind, _inc($ind), _inc($ind), _inc($ind), _inc($ind)];
$straight = count(array_intersect($s, $cards)) == count($s);
if ($straight) break;
}
print $straight;
您可以对卡片进行排序并在数组中循环遍历它们 - 始终保存最后一张卡片并将它们与当前卡片进行比较。
$cards = array(12,5,6,7,4,11,3);
sort($cards);
$last = 0;
$count = 0;
$wheel = false;
foreach ($cards as $card) {
if ($card == $last) {
continue;
} else if ($card == ++$last) {
$count++;
} else {
if ($last == 6) $wheel = true;
$count = 1;
$last = $card;
}
if ($count == 5 || ($card == 14 && $wheel)) {
echo "straight $last";
$straight = range($last - 4, $last);
break;
}
}
我已经成功地创建了一个算法来检查一手牌的排名。它 100% 正确地工作,但速度很慢。我一直在分析代码,check straight 函数是其中最慢的部分之一。
所以我的问题是,有没有更好的方法来计算一手牌是否顺子?
这里有一些细节:
7 张牌,持有人 2 张,牌面 5 张。 A 可高可低。
每张卡片都分配了一个值: 2 = 2 3 = 3 .. 9 = 9 T = 10 J = 11 问 = 12 K = 13 A = 14
该脚本包含所有 7 张卡片的数组:
$cards = array(12,5,6,7,4,11,3);
所以现在我需要能够将其排序到一个数组中:
- 丢弃重复项
- 卡片从低到高排序
- 只有 returns 5 张连续的牌,即(3,4,5,6,7)
要快;循环和迭代非常昂贵。这是我目前使用的,当它试图分析 15000 手牌时,它会对脚本造成影响。
对于以上,我使用了:
- 丢弃重复项(使用array_unique)
- 从低到高排序卡片(使用 sort())
- 只有return 5张连续的卡片(使用for循环检查卡片的值)
有没有人有任何我可以改进的例子?甚至可以用另一种语言,我也许可以看看它是如何完成的?
与其使用数组重复数据删除和排序,不如考虑使用位掩码,并将设置卡值的位设置为 1。位掩码的工作方式类似于 Set 数据结构,并且在检测连续元素时具有额外的优势。
for ($i = 0; $i < count($cards); $i++) {
$card = $cards[$i];
// For each card value, set the bit
if ($card == 14) {
// If card is an ace, also set bit 1 for wheel
$cardBitmask |= 0x2;
}
$cardBitmask |= (1 << $card);
}
// To compare, you simply write a for loop checking for 5 consecutive bits
for($i = 10; $i > 0; $i--)
{
if ($cardBitmask & (0x1F << $i) == (0x1F << $i)) {
// Straight $i high was found!
}
}
考虑 this link 的 Java 实施。我把它放在这里了:
public static boolean isStraight( Card[] h )
{
int i, testRank;
if ( h.length != 5 )
return(false);
sortByRank(h); // Sort the poker hand by the rank of each card
/* ===========================
Check if hand has an Ace
=========================== */
if ( h[4].rank() == 14 )
{
/* =================================
Check straight using an Ace
================================= */
boolean a = h[0].rank() == 2 && h[1].rank() == 3 &&
h[2].rank() == 4 && h[3].rank() == 5 ;
boolean b = h[0].rank() == 10 && h[1].rank() == 11 &&
h[2].rank() == 12 && h[3].rank() == 13 ;
return ( a || b );
}
else
{
/* ===========================================
General case: check for increasing values
=========================================== */
testRank = h[0].rank() + 1;
for ( i = 1; i < 5; i++ )
{
if ( h[i].rank() != testRank )
return(false); // Straight failed...
testRank++; // Next card in hand
}
return(true); // Straight found !
}
}
快速 Google 搜索 "check for poker straight (desired_lang)
" 将为您提供其他实现。
你可以这样走,你不需要排序或任何东西(假设2是2,14是ace):
$cards = [12,5,6,7,4,11,3];
function _inc(&$i) {
if ($i == 14)
$i = 2;
else
$i++;
return $i;
}
$straight = false;
for($i = 2; $i <= 14; $i++) {
$ind = $i;
if (!in_array($ind, $cards)) continue;
$s = [$ind, _inc($ind), _inc($ind), _inc($ind), _inc($ind)];
$straight = count(array_intersect($s, $cards)) == count($s);
if ($straight) break;
}
print $straight;
您可以对卡片进行排序并在数组中循环遍历它们 - 始终保存最后一张卡片并将它们与当前卡片进行比较。
$cards = array(12,5,6,7,4,11,3);
sort($cards);
$last = 0;
$count = 0;
$wheel = false;
foreach ($cards as $card) {
if ($card == $last) {
continue;
} else if ($card == ++$last) {
$count++;
} else {
if ($last == 6) $wheel = true;
$count = 1;
$last = $card;
}
if ($count == 5 || ($card == 14 && $wheel)) {
echo "straight $last";
$straight = range($last - 4, $last);
break;
}
}