I’m working on a very small blackjack game in PHP.
I’m currently writing the function to count the cards, but the aces are kicking my butt.
My cards are all in an array like this:
$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");`
Where the first character is the suit and everything after that is the card (j for jack, etc)
Here’s what I have for counting the values up so far:
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);
}
}
}
Originally, I also had the ace in there valued at 11, but obviously that would cause problems. I feel like I need to keep relooping to make sure the aces don’t put us over 21, but I’m not entirely sure of the best way to go about doing that.
I’d appreciate some input, guys.
EDIT:
The best I can think of is adding this to the function
foreach ($cards as $card) {
if (substr($card, 1) == "a") {
if ($card_values + 11 <= 21) {
$card_values += 11;
}
else {
$card_values += 1;
}
}
}
Actually I think this might work. Give me a few minutes to test.
EDIT:
Nope, didn’t work. 4, ace, ace, 6 came out to 22 with this.
I do not know much about BlackJack, but this is my try.
UPDATE
If I understand your other comment, you want 6 4 A A A to come out 13, 6 4 A A to come out 12, and 6 4 A to come out 21. So the number of remaining aces count. Modified the source accordingly.
Explanation
First of all we calculate the value of non-ace cards. These are constant, so we get it over with. And this total is the (preliminary)
$card_values.Then we may have (or not) some aces. It makes sense to have a
while($aces)so that if we have no aces, we do nothing.And now the question is, what do we do with those aces? Here is where your requisite comes in: the sum must fit into 21. This means that I can’t just say “I’m at 10, I have an ace, so it fits into 21” because there might be another ace after that. So I have to calculate what would the worst case be if I were to add in all remaining aces; and that’s of course the number of aces, times 11. While the worst case is still good (i.e.,
$card_values + 11*$aceis less than 21) I can add 11. While it is not, I have to add 1.It is a form of “greedy” algorithm: I fit in all the 1’s we can, while ensuring enough 11’s are left to reach the closest approach to 21 that does not exceed.
I seem to remember (I might be wrong, heh) that there was a nasty bug in this implementation which will come out whenever NumberOfItems * LowestValue >= HighestValue (I’m not too sure about that “equals” though). But in this case, it would require NumberOfItems to be above 11/1 = 11 aces, and there are not so many aces in the deck, so we’re cool. And to be sure, the possible cases are five – from “no” to “four” aces in a hand – and easily tested for all sums of other cards:
The output (version 1)
Current output (added code to only print errors):