PHP Diary | PHP Housekeeping | PHP Scripts | TD Scripts.com
TD Pic of Day PHP - Run your own picture of the day script from any site anywhere with this handy script


[back]
WB01624_.gif (281 bytes) 01/21/00 "Shuffling a deck of cards" WB01626_.gif (272 bytes)[next]

First PHP script released (beta)

If you are on the php-scripts mailing list I made in these diary entries then you should have received notification today that the beta release of an original card game I am calling Guts or Glory poker was made playable on the site today (see main page for the link). I wanted to share here a technique or two I employed using PHP and this script, as it presented some unique challenges I haven't previously covered. Also, since I was embroiled in the coding I haven't had a chance to sneak over here and update this diary. This isn't a blow-by-blow description of how my game was created, but it is a concept you can use to take and make other card games of your own.

Shuffling a deck of cards - getting 52 unique, yet random numbers

In almost any card game you will need a shuffled deck of cards to play with. If you read my prior entry on random number generation, we have already touched upon how to generate random numbers (12/27/99). Shuffling a deck of cards is a little more tricky because you can't simply keep picking a number between 1 and 52 or you will almost certainly pick the same number more than once (and thus have duplicates of the same card). The technique I employed, and by no means am I suggesting this is the only way to shuffle a deck of cards, was to randomly draw from an array of 52 cards, destroy the chosen card, and then fill a second array until there were no more valid cards in our original array. This second deck of cards would then be the shuffled deck and we could proceed.  Firstly, names like ace_of_clubs and ten_of_hearts were a little too unwieldy for me to use, so I abbreviated them to the first digit for the value of the card and the second digit for the suit of the card ("d" for diamonds, "c" for clubs, "s" for spades, "h" for hearts). Here's how my cards array looks:

$cards = array("ah", "ac", "ad", "as",
               "2h", "2c", "2d", "2s",
               "3h", "3c", "3d", "3s",
               "4h", "4c", "4d", "4s",
               "5h", "5c", "5d", "5s",
               "6h", "6c", "6d", "6s",
               "7h", "7c", "7d", "7s",
               "8h", "8c", "8d", "8s",
               "9h", "9c", "9d", "9s",
               "th", "tc", "td", "ts",
               "jh", "jc", "jd", "js",
               "qh", "qc", "qd", "qs",
               "kh", "kc", "kd", "ks");

As you can see i changed the ace to "a", the 10 to "t", jack to "j", queen to "q", king to "k", and ace to "a" to stay consistent with the 2 digit format. The next task is creating the random number routine which will pull 52 cards out of this array. When I looked at random numbers before, I didn't really talk much about seeds and their importance in random generation. You ever been to the casino and watched them shuffle the cards? The dealer opens the deck spreads the cards out and the spreads and mixes the cards repeatedly on the felt face down. Now they are already in a random order, but that isn't random enough for the casinos, so they begin shuffling the cards repeatedly. It still isn't quite random enough, so next the dealer shuffles the cards and then either cuts the cards or has a rotating player (thus randomizing because no two players will usually pick the exact starting point) pick a place to cut the cards, essentially starting at a random point. Now the dealing of the cards can begin. This is about as random a process as you will find and no computer can perfectly replicate this process since it operates on a deterministic model. However, by using a sophisticated seed generation you can come pretty darn close to true random number generation. The seed is what the computer will use to determine the pattern by which to randomize the number and the more random a number you want or need, the more sophistocated the algorithm should be. A less sophistocated type of seed will work in most situations and that is using the function time, such as:

srand(time());

This determines the random pattern the cards will be generated with using the seconds in the current server time. I used it before in my example and I'll use it again here. Now let's examine the loop to randomly pull cards from the array and create a shuffled deck array of cards:

srand(time());
for($i = 0; $i < 52; $i++)
{
   $count = count($cards);
   $random = (rand()%$count);
   if($cards[$random] == "")
  {
    $i--;
  }
   else
  {
     $deck[] = $cards[$random];
     $cards[$random] = "";
  }
}

Line 1: this is the see for the number generator, in this example the time() function
Line 2: start the loop, from 0 (remember arrays start numbering at zero not 1) to 51. If $i in the loop iteration should be less than 52 then go ahead and pull another random number.
Line 4,5: pick a random number
Line 6-9: if the random number we pick, corresponding to the card array is empty, then pick another random number (this is not a valid card).
Line 10-14: the card is valid so add the card to the $deck array and then destroy its value in the $cards array so it cannot be chosen again.

Now that you have a shuffled deck of cards, you can essentially "cut" the cards by choosing a starting point for cycling through your array. We need one random number between 0 and 51 to determine this starting point. Here's the final bit of code to cut the cards:

<?
srand(time());
$starting_point = (rand()%51);
print("Starting point for cut cards is $starting_point");
?>

The last thing to do is to illustrate how to cycle through the array using the starting point as the beginning on the cards to deal. We can accomplish this using another for loop and displaying the shuffled deck using the $starting_point as an index. The catch here is we have to build in an if statement to make sure that when the count reaches 52 we reset the $starting_point to zero so the cards will be cycled. Here is the code to accomplish this:

for ($index = 0; $index < 52; $index++)
{
if ($starting_point == 52) { $starting_point = 0; }
print("Uncut Point: <strong>$deck[$index]</strong> ");
print("Starting Point: <strong>$deck[$starting_point]</strong><br>");
$starting_point++;
}

You may notice that the actual starting point is one number after the $starting_point, which is by design. You could subtract one from the starting point if you wanted to truly start at that number. The "Uncut Point" is the shuffled deck array in its original form from left to right. You can take the number at the top and count down and you'll see where the order on the right side starts looking familiar to that on the left.

Example #25: Shuffling and "cutting" a deck of cards

Please vote on the usefulness of this diary entry so other people will know if it is worth their time to read :)

How useful was this diary entry? Avg Surfer Rating: 3.55 (214)

[back]WB01624_.gif (281 bytes) 01/21/00 "Shuffling a deck of cards" WB01626_.gif (272 bytes)[next]

PHP Diary | PHP Housekeeping | PHP Scripts | TD Scripts.com

Copyright 2000 php-scripts.com Last Modified 01/21/00 01:46