我正在使用PHP进行一个非常小的二十一点游戏。
我目前正在编写计算卡片的功能,但是ace会踢我的屁股。
我的卡片都是这样的数组:
$card_array = array( "ca", "c10", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9",
"cj", "ck", "cq", "da", "d10", "d2", "d3", "d4", "d5", "d6", "d7", "d8",
"d9", "dj", "dk", "dq", "ha", "h2", "h3", "h4", "h5", "h6", "h7", "h8", "h9",
"hj", "hk", "hq", "sa", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9",
"s10", "sj", "sk", "sq");`
第一个角色是套装,之后的所有内容都是卡片(j代表杰克等)
这是我到目前为止计算值的原因:
function bj_calculate_values( $cards ) {
$card_values = 0;
foreach ($cards as $card) {
if (substr($card, 1) == "k" || substr($card, 1) == "q" || substr($card, 1) == "j") {
$card_values += 10;
}
else if (substr($card, 1) != "a") {
$card_values += substr($card, 1);
}
}
}
最初,我也有一张价值11的ace,但显然这会引起问题。我觉得我需要继续重新开口,以确保A不会让我们超过21岁,但我并不完全确定这样做的最好方法。
我很感激一些意见,伙计们。 的修改:
我能想到的最好的就是将其添加到函数
中foreach ($cards as $card) {
if (substr($card, 1) == "a") {
if ($card_values + 11 <= 21) {
$card_values += 11;
}
else {
$card_values += 1;
}
}
}
实际上我觉得这可行。给我几分钟的时间来测试一下。
修改
不,不行。 4,ace,ace,6用这个来到了22。答案 0 :(得分:3)
我对BlackJack了解不多,但这是我的尝试。
function bj_calculate_values( $cards ) {
$card_values = 0;
$ace = 0;
foreach ($cards as $card) {
$val = substr($card, 1);
if (!is_numeric($val))
{
if ('a' == $val)
{
$val = 0;
$ace ++;
}
else
$val = 10;
}
$card_values += $val;
}
while ($ace)
$card_values += ($card_values + 11*$ace-- <= 21) ? 11: 1;
return $card_values;
}
如果我理解你的其他评论,你想要6 4 AAA出来13,6 6 4 AA出来12,6和4 4 A出来21.所以剩余 aces的数量计数。相应地修改了源。
首先,我们计算非一张牌的价值。这些是不变的,所以我们把它解决了。这个总数是(初步)$card_values
。
然后我们可能有(或没有)一些ace。有一个while($aces)
是有道理的,这样如果我们没有王牌,我们什么都不做。
现在的问题是,我们如何处理这些A?这是你的必备条件:总和必须符合21。这意味着我不能只说“我是10岁,我有一个王牌,所以它适合21”因为可能有另一个之后 ace。因此,如果我要添加所有剩余的A,我必须计算最差的情况。这当然是次数,次数11.虽然最坏的情况仍然很好(即$card_values + 11*$ace
小于21)我可以加11.虽然不是,但我必须加1。
这是一种“贪婪”的算法:我尽可能地适应所有的1,同时确保留下足够的11,以达到最接近21的不超过。
我似乎记得(我可能错了,嘿)这个实现中有一个讨厌的错误,只要NumberOfItems * LowestValue&gt; = HighestValue就会出现(虽然我不太确定“等于”) 。但是在这种情况下,它需要NumberOfItems超过11/1 = 11个ace,并且牌组中没有那么多A,所以我们很酷。可以肯定的是,可能的情况是五个 - 从手中的“不”到“四个” - 并且很容易测试所有其他卡的数量:
// J Q K are worth 10, so we can use 10 instead.
// And a fake card with value of 0 stands for "nothing".
// We use the suit of Klingon, with up to four identical aces :-D
for ($first = 0; $first <= 21; $first++)
{
$hand = array("k$first");
for ($aces = 1; $aces < 5; $aces++)
{
$hand[] = "ka";
$value = bj_calculate_values($hand);
// Let us ponder the possible values of $value.
if ($value <= 11)
{
// This is an error: we could have gotten closer to 21
// by upvaluing an ace. A correct implementation will
// never enter here except in the case of a LONE ACE.
if (($first != 0) || ($aces != 1))
print "ERROR: " . implode(" ", $hand) . " = $value\n";
}
// We have a value from 12 to 21.
// Could we have done better? What cards do we have?
// If no aces, of course no. All card values are then fixed.
// If at least one ace, interpreted as 11, again not:
// cannot interpret it above 11, and interpret as 1 would LESSEN the score.
// If at least one ace, interpreted as 1, were we to interpret it
// as 11, we would be summing 10. And 12 would become 22, and blow.
// So, from 12 to 21, the result MUST be correct.
// Finally, $value more than 21.
if ($value > 21)
{
// This is admissible ONLY if we could have done no better, which
// means $value is given by the fixed cards' value, $first, plus
// ALL ACES COUNTED AS ONES.
if ($value != ($first + $aces))
print "ERROR: " . implode(" ", $hand) . " = $value\n";
}
}
}
输出(版本1)
VERIFY: k0 ka = 11 Correct, we had a lone ace and gave it 11.
VERIFY: k18 ka ka ka ka = 22 Correct, we had 18 in other cards and all A's to 1's.
VERIFY: k19 ka ka ka = 22 Ditto, 19 in cards.
VERIFY: k19 ka ka ka ka = 23 Ditto, 19 in cards.
... ...
当前输出(仅添加代码以打印错误):
-- nothing :-)