直接检查扑克

时间:2015-10-01 21:04:43

标签: php arrays algorithm sorting poker

我设法创建了一个算法来检查扑克牌的排名。它100%正确工作,但速度很慢。我一直在分析代码,而直接检查功能是其中最慢的部分之一。

所以我的问题是,有没有更好的方法来计算一只手是否伸直?

以下是一些细节:

7张牌,2张牌,5张牌。 A可以高或低。

每张卡都分配了一个值:     2 = 2     3 = 3     ..     9 = 9     T = 10     J = 11     Q = 12     K = 13     A = 14

该脚本包含所有7张卡的数组:

$cards = array(12,5,6,7,4,11,3);

所以现在我需要能够将它排序到一个数组中:

  • 丢弃重复项
  • 从最低到最高订购卡
  • 只返回5张连续牌。 (3,4,5,6,7)

它需要快速;循环和迭代非常昂贵。这就是我目前使用的,当它试图分析说15000手时,它会对脚本产生影响。

对于上述内容,我使用了:

  • 丢弃重复项(使用array_unique)
  • 从最低到最高的订单卡(使用sort())
  • 仅返回5张连续牌(使用for循环检查牌的值)

有没有人有任何关于如何改进这方面的例子?也许甚至用另一种我可能会看到的语言看看它是如何完成的?

4 个答案:

答案 0 :(得分:4)

不要使用数组重复数据删除和排序,而是考虑使用位掩码,并将位设置为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!
    }
} 

答案 1 :(得分:1)

考虑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快速搜索&#34;直接查看扑克(desired_lang)&#34;将为您提供其他实施。

答案 2 :(得分:1)

您可以对卡片进行排序并在阵列中循环它们 - 始终保存最后一张卡片并将其与当前卡片进行比较。

$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;
    }
}

答案 3 :(得分:0)

你可能会这样,你不需要排序或任何东西(假设2是2和14是王牌):

$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;