0

I've got a question. I've build this PHP script, it works just fine, except for the fact that aces don't work properly. If I draw 5 A 5 5, it thinks I have 26 etc.

Does anyone know how to solve this problem? Function to evaluateHand:

function evaluateHand($hand) {

global $faces;
$value = 0;
foreach ($hand as $card) {

    $values = explode("|",$card);
    $value1= $values[0];

    if($value1=="Q" OR $value1=="J" OR $value1=="K"){
        $value = intval($value) + 10;
    }

    if ($value > 10 && $value1 == "A") {
        $value = intval($value) + 1;  // An ace can be 11 or 1
    }
    elseif($value < 12 && $value1 == "A"){
                   $value = intval($value) + 11;  // An ace can be 11 or 1
        }

     else {
        $value = intval($value) + intval($value1);
    }
}
return $value;
}
Linus Kleen
  • 33,871
  • 11
  • 91
  • 99
  • 3
    `global $faces;`? code smell? – maček Nov 22 '12 at 09:51
  • What do you mean? Faces is declared up top with: $suits= array("spades","clubs","hearts","diamonds"); $faces = array (1 => "A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"); – Babak Zahedi Nov 22 '12 at 09:53
  • Also what's with the `$values = explode('|', $card);`? I'm guessing a card is something like `"A|spades"` or `"10|clubs"`? Get your cards based on a good model first, then the logic for adding them shouldn't be so difficult. See [my answer](http://stackoverflow.com/a/2641421/184600) to this question here for how to setup a deck of cards in Ruby. – maček Nov 22 '12 at 09:59

4 Answers4

1

Sort the list of cards so that aces are evaluated last.

Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
  • You can find my whole script over here: http://pastebin.com/XNmVTp8h It is actually based on a good model (in my opinion), althoug the aces don't work properly yet. – Babak Zahedi Nov 22 '12 at 10:00
  • Works, but not in all cases. 2, A, Q gives 23.. while it should give 13. – Babak Zahedi Nov 22 '12 at 10:08
  • @BabakZahedi — The "A" is not being evaluated last. Don't sort the list alphabetically, sort it so that aces are evaluated last. – Quentin Nov 22 '12 at 10:09
0

Why global $faces;?

To make your code working just add asort($hand); in the top of the function. This will order the array, to put the A as last.

EDIT: You are right. I have changed the function to always evaluate the aces as last.

function evaluateHand($hand) {
    global $faces;
    $value = 0;
    $aces = 0;
    foreach ($hand as $card) {
        $values = explode("|",$card);
        $value1= $values[0];

        if($value1 == "A") {
            $aces++; 
        }
        else {
            if($value1=="Q" OR $value1=="J" OR $value1=="K"){
                $value = intval($value) + 10;
            }
            else {
                $value = intval($value) + intval($value1);
            }
        }
    }

    while($aces > 0) {
        if($value > 10) {
            $value = intval($value) + 1;
        }
        elseif($value < 12){
               $value = intval($value) + 11;  // An ace can be 11 or 1
        }
        $aces--;
    }

    return $value;
}
noslone
  • 1,301
  • 10
  • 14
0

As you said in one of the comments, the asort alone won't work, as the sorting goes like this: 0-9, then A to Z, so The Aces are still being checked before the other figures.

I modified a bit your function so it works better in that way:

function evaluateHand($hand) {
        asort($hand);
        print_r($hand);

        $aces = 0;

        global $faces;

        $value = 0;
        foreach ($hand as $card) {

            $values = explode("|",$card);
            $value1= $values[0];

            if($value1=="Q" OR $value1=="J" OR $value1=="K"){
                $value = intval($value) + 10;
            } elseif($value1 == "A") {
                $aces++;
            } else {
                $value = intval($value) + intval($value1);
            }

        }

        if($aces > 0){
            for($a = 0; $a < $aces; $a++){
                if ($value > 10) {
                    $value = intval($value) + 1;  // An ace can be 11 or 1
                }elseif($value < 12){
                    $value = intval($value) + 11;  // An ace can be 11 or 1
                }
            }
        }

        return $value;
    }

What I have done is create an Aces counter ($aces = 0), and when there's an Ace we skip the sum, and increase the counter, after the foreach loop then we sum the desired value based on the total value of the hand, with another loop based on the aces we have in the array.

aleation
  • 4,796
  • 1
  • 21
  • 35
0

As Quentin said, treat aces last. Also count how many aces there are in the hand (to avoid giving 11 to one ace and overflow if you have, let's say, three aces, instead of counting 1+1+1). Treat all aces together, dividing the number of points left by the number of aces. If result is superior to 11, give 11 to one and 1 to the others. If not, give 1 to all aces.

barakadam
  • 2,179
  • 1
  • 16
  • 15
  • 1
    how would I count all aces in the hand then? – Babak Zahedi Nov 22 '12 at 10:03
  • Loop through the hand array and add 1 to a counter each time you have an ace. When the loop is finished, the counter tells you how many aces you have in the hand. – barakadam Nov 22 '12 at 10:08
  • If you are having problems sorting, then try creating an array of aces, and adding each ace encountered during the loop. That way you can loop through the aces as the end, and you can use count($aces) to figure out how many aces you have. – Paul S Nov 22 '12 at 10:12