<?PHP
/*
THIS IS A SIMPLE PROGRAM TO DEAL A SEQUENCE OF CARDS
FOR NO OR ANY PARTICULAR PURPOSE FROM A STANDARD
52-CARD DECK WITHOUT REPLACEMENT.
AUTHOR : Jay Tanner
LANGUAGE : PHP 5.2.4 - Revised with PHP 8.2.12
REVISED : 2025-Sep-12-Fri
THIS PROGRAM EXPECTS THE CARD IMAGE FILES TO BE IN
THE SAME FOLDER AS THIS PROGRAM.
*/
// *********************************************
// *********************************************
$ProgramVersion = "4.1";
// ------------------------------------------
// Read current year value from system clock.
$year = date("Y");
// ----------------
// Get script name.
$_ACTION_FILE_NAME_ = $_SERVER['SCRIPT_NAME'];
// ------------------------------------
// Define internal HTML web page title.
$_INTERNAL_HTML_PAGE_TITLE_ = "Random N-Cards Dealer";
// -----------------------------
// Read number of cards to draw.
$N = IntVal(trim(@$_POST['N']))+0;
if ($N < 0) {$N = 1;}
if ($N == 0) {$N = 5;}
if ($N > 52) {$N = 52;}
$s = ($N > 1)? "s" : "";
$WOR = ($N <> 1 and $N <> 52)? " Without Replacement " : "";
$ALL = ($N == 52)? 'All ':'';
$decimals = 2;
$CombNum = bcComb_N_R ('52', $N);
$CombNumName = 'About ' . BC_Big_Int_Name ($CombNum, $decimals) . ' to 1';
$CombinationOdds = Number_Format($CombNum);
if ($CombNum < 1000000) {$CombNumName = '';}
$PermNum = bcPerm_N_R ('52', $N);
$PermNumName = 'About ' . BC_Big_Int_Name ($PermNum, $decimals) . ' to 1';
$PermutationOdds = Number_Format($PermNum);
if ($PermNum < 1000000) {$PermNumName = '';}
// ------------------------------------
// Define page heading text to display.
$_PAGE_HEADER_ = "<B style='font-size:125%;'>Random Cards Dealer</B><br><span style='font-size:12pt;'>From Standard 52-Card American Deck</span>";
$RandomColor = '';
/* ------------------------------------------
Deal a random sequence of cards from a
standard 52-card deck without replacement.
The cards are returned as an HTML encoded
card image file names string.
*/
$CardsDrawn = "\n" . Draw_N_Cards($N);
/*
#################################################
This function draws a sequence of N random cards
from a standard 52-card deck without replacement.
#################################################
*/
function Draw_N_Cards($ArgN)
{
// Read the N argument.
$N = trim($ArgN)+0;
// If N <= 0 then return empty string.
if ($N <= 0) {return '';}
// Initialize array for card deck.
$cards = Array();
// Initialize HTML image code string.
$DrawnCards = '';
// Create an array and fill it with the 52-cards.
for ($i=0; $i < 52; $i++) {$cards[$i] = $i+1;}
// Shuffle the deck three times.
shuffle($cards);
shuffle($cards);
shuffle($cards);
// Draw the requested number of cards
// from the top of the shuffled deck.
for ($i=0; $i < $N; $i++)
{
// Get current card ID (1 to 52)
// from card deck array.
$CardID = $cards[$i];
// Compute suit code number (1 to 4)
$CardSuitCode = floor(($CardID-1) / 13) + 1;
// Encode card rank number (1 to 13)
$CardRank = ($CardID % 13) + 1;
// Compute hex code equivalent to decimal card
// rank and force to upper case letters.
$CardRankHex = StrToUpper(DecHex($CardRank));
// Construct numerical card code. This will
// always be two hexadecimal digits that
// uniquely identify each card by suit
// and rank.
$CardCode = "$CardSuitCode$CardRankHex";
// Create image ALT text (full card name) from card ID code.
$CardName = CardCode_to_CardName($CardCode);
// print "*** CardCode = $CardCode = $CardName ***";
// Construct card image file name.
$CardImageFileName = "$CardCode.png";
// Construct HTML encoded image file tag for the current
// card and attach to string of accumulated cards.
$DrawnCards .= "<IMG SRC=\"$CardImageFileName\" ALT=\" $CardName \" BORDER=\"1\">\n";
}
// Done
return $DrawnCards;
} // End of Draw_N_Cards()
/*
This function generates the card deck in sequential order
by suit and rank, or the direct opposite of shuffling into
a random order.
NOT DONE YET
*/
function Standard_Card_Deck()
{
$w = Draw_N_Cards(52);
return $w;
}
/*
##############################################
This function returns the full-text name of
a card. For example 212 as an input argument
would return the string "Queen of Clubs" as
the card name.
##############################################
*/
function CardCode_to_CardName ($CardCodeArg)
{
$CardSuitCode = preg_split("[ ]", "Diamonds Clubs Hearts Spades");
$SuitCode = substr($CardCodeArg, 0, 1)+0;
$SuitName = $CardSuitCode[$SuitCode-1];
$RankCode = HexDec(substr($CardCodeArg, 1, strlen($CardCodeArg)));
$RankName = $RankCode;
if ($RankCode == 1) {$RankName = "Ace";}
if ($RankCode == 11) {$RankName = "Jack";}
if ($RankCode == 12) {$RankName = "Queen";}
if ($RankCode == 13) {$RankName = "King";}
return "$RankName of $SuitName";
}
// PHP BLOCK ENDS HERE
// *********************************************
// *********************************************
// THE HTML BLOCK BEGINS HERE.
print <<< _HTML
<!DOCTYPE HTML>
<HTML>
<HEAD>
<TITLE>Random Playing Cards Dealer</TITLE>
<meta name='viewport' content='width=device-width, initial-scale=1'>
<meta http-equiv='content-type' content='text/html; charset=UTF-8'>
<meta name='description' content='This PHP program simply deals a given number of playing cards without replacement from a standard American deck of 52 cards.'>
<meta name='keywords' content='card dealer,random cards,random card dealer,PHPScienceLabs.com'>
<meta name='author' content='Jay Tanner - NeoProgrammics.com / PHPScienceLabs.com'>
<meta http-equiv='pragma' content='no-cache'>
<meta http-equiv='expires' content='-1'>
<meta name='robots' content='index,follow'>
<meta name='googlebot' content='index,follow'>
<style type='text/css'>
BODY {color:white; background-color:black; font-family:Verdana; font-size:14px}
TABLE {font-family:Verdana; font-size:14px;}
TD {color:black; background-color:white; line-height:150%; font-size:14px; padding:6px; text-align:center;}
LI {text-align:justify;}
DIV, P {color:black; background-color:white; font-family:Verdana; text-align:left; padding:6px; font-size:14px;}
PRE {color:black; background-color:white; font-family:monospace; font-size:16px; font-weight:bold; text-align:left; border:1px solid black; border-radius:8px; box-shadow:4px 4px 3px #999999; padding:4px;}
CODE {font-family:monospace; font-size:16px; font-weight:bold;}
TEXTAREA {color:black; background-color:white; font-family:monospace; font-size:18px; font-weight:bold; box-shadow:4px 4px 3px #999999; border-radius: 8px; border:1px solid black; padding:4px; white-space:pre;}
IMG {border:1px solid black; box-shadow:3px 4px 5px #444444; border-radius:4px;}
INPUT[type='text']::-ms-clear {width:0; height:0;}
INPUT[type='text']{color:black; background-color:white; border-radius:4px; font-family:monospace; font-size:18px; font-weight:bold; text-align:center; box-shadow:2px 2px 3px #999999; border:2px solid black;}
INPUT[type='text']:focus {color:black; background-color:white; border-radius:4px; font-family:monospace; font-size:18px; font-weight:bold; text-align:center; box-shadow:2px 2px 3px #666666; border:2px solid blue;}
INPUT[type='submit']{font-size:100%; font-weight:bold; border:1px solid black; border-radius:4px;}
INPUT[type='submit']:hover {font-size:100%; box-shadow:2px 3px 4px #222222; background:cyan; font-weight:bold; border:1px solid black; border-radius:4px;}
INPUT[type='checkbox']:checked {box-shadow:2px 2px 3px #222222;}
INPUT[type='radio']:checked {box-shadow:2px 2px 3px #222222;}
HR {background-color:black; height:2px; border:0px;}
A:link {background-color:transparent; color:blue; font-family:Verdana; font-size:14px; font-weight:bold; text-decoration:none; line-height:150%; padding:2px;}
A:visited {background-color:transparent; color:DarkCyan;}
A:hover {background-color:transparent; color:red;}
A:active {background-color:transparent; color:red;}
::selection {background:yellow; color:black;} /* IE9+ and Safari */
::-moz-selection {background:yellow; color:black;} /* FireFox and Mozilla */
</style>
</HEAD>
<BODY style='background:black;'>
<TABLE width='1150' BGCOLOR="black" ALIGN="top" BORDER="0" CELLSPACING="1">
<tr><td style='color:white; background:#000066; border:2px solid white; border-radius:8px 8px 0px 0px;'>
<H3 ALIGN="center"><B style='font-size:20pt; font-weight:normal;'>Random Playing Cards Dealer</B><br><span style='font-size:10pt;'>Using a Standard 52-Card American Deck</span><br><span style='font-size:8pt;'>PHP Program by Jay Tanner</span></H3>
<a href='View-Source-Code.php' target='_blank'
style='font-family:Verdana; color:black; background:yellow;
text-decoration:none; border:1px solid black; padding:4px;
border-radius:4px;'>
<span style='font-weight:normal;'>View/Copy PHP Source Code</span> </a>
</td></tr>
<TR>
<TD style="background:GreenYellow;">$CardsDrawn</TD>
</TR>
<tr><td style='color:black; background:LightYellow;'>
<b style='font-size:11pt; line-height:300%;'>For $ALL$N Card$s Randomly Drawn$WOR From a Standard 52-Card Deck:</b>
<br>
The odds of drawing ALL of the cards contained in the combination shown above,<br>REGARDLESS OF THE SEQUENCE in which which they were drawn, are:<br><code>$CombinationOdds : 1</code><br>
$CombNumName
<hr>
The odds of the making any draw are the same as the odds of predicting the draw.
<hr>
The odds of drawing ALL of the cards shown above, in the<br>SAME EXACT SEQUENCE as shown, are :<br><code>$PermutationOdds : 1</code><br>
$PermNumName
<br>
</td></tr>
<tr><td style="background-color:LightCyan; border-radius:0px 0px 8px 8px;">
<FORM ACTION="$_ACTION_FILE_NAME_" METHOD="post">
<!--
<TABLE WIDTH="1150" BGCOLOR="black" CELLPADDING="2" BORDER="0" CELLSPACING="1">
-->
<B>Number of Cards to Draw</B> (<B>1</B> to <B>52</B>)<B> ? </B>
<INPUT NAME="N" TYPE="text" SIZE="3" MAXLENGTH="2" VALUE="$N">
<INPUT TYPE="submit" NAME="Deal_Cards_Button" VALUE="Deal the Card$s">
<BR>
<BR>
</FORM>
Each card sequence drawn is fresh and totally independent of any previous drawings.<br>
</td></tr>
</TABLE>
<!--
<A HREF="display_all_cards.php"> Display Whole Deck</A>
-->
<br><br><br><br><br><br><br><br><br><br><br><br>
<br><br><br><br><br><br><br><br><br><br><br><br>
</BODY>
</HTML>
_HTML;
// THE HTML BLOCK ENDS HERE.
// *********************************************
// *********************************************
// PHP BLOCK BEGINS HERE.
/*
These functions are used to compute the basic probabilities of each
drawing.
*/
/*
==========================================================================
This function returns the EXACT number all possible random combinations
of (R) items selected from a total set of (N) unique items available.
NOTE: In combinations, only which items are in the selected group matters.
The sequential order in which the items are selected or arranged does not
matter.
Regardless of order, no two groups contain exactly the same set of items.
RULE: (N, R) are non-negative integers where 0 <= R <= N
This function uses arbitrary-precision Binary Calculator (BC) arithmetic
which can return exact values up to several thousands of digits long.
==========================================================================
*/
function bcComb_N_R ($N, $R)
{
$C = 1; $j = $N - $R;
for ($i=0; $i < $j; $i++)
{$C = bcDiv(bcMul($C, $N-$i), $i+1);} return $C;
}
/*
===========================================================================
This function returns the EXACT count of unique permutations of (N) items
that are possible when selected in random groups of (R) at a time.
NOTE: In permutations, the sequential line order of items in each group
IS important. No two selected sequences are in the same order.
Permutations refers to the physical count of the number of unique sequences
into which we can arrange the items within a row, line or column.
RULE: (N, R) are non-negative integers where 0 <= R <= N
This function uses arbitrary-precision BC (Binary Calculator) arithmetic
which can return exact values up to several thousands of digits long.
===========================================================================
*/
function bcPerm_N_R ($N, $R)
{
$P=1; for ($i=0; $i < $R; $i++) {$P = bcMul($P, $N-$i);} return $P;
}
/*
----------------------------------------------------------------------------
This function returns the formal names of very large
integers up to a limit of 99 digits length.
The American system of numerical nomenclature is used.
Arguments:
$BigIntStr = Large integer as a string (1 million and above).
$LabelStr = Optional lable string suffix to attach to output.
----------------------------------------------------------------------------
*/
function BC_Big_Int_Name ($BigIntStr, $Decimals=2)
{
$BigInt = Str_Replace(',' ,'', Str_Replace(' ' ,'', trim($BigIntStr)));
$DigitsCount = StrLen($BigInt);
$decimals = trim($Decimals);
// ------------------------------------------------
// Break up big integer into spaced 3-digit groups
// and count the number of groups.
$DigitGroupsStr = '';
$BigInt = StrRev($BigInt);
// ***************
// ***************
$groups[1] = '';
$groups[2] = 'thousand';
$groups[3] = 'million';
$groups[4] = 'billion';
$groups[5] = 'trillion';
$groups[6] = 'quadrillion';
$groups[7] = 'quintillion';
$groups[8] = 'sextillion';
$groups[9] = 'septillion';
$groups[10] = 'octillion';
$groups[11] = 'nonillion';
$groups[12] = 'decillion';
$groups[13] = 'undecillion';
$groups[14] = 'duodecillion';
$groups[15] = 'tredecillion';
$groups[16] = 'quattuordecillion';
$groups[17] = 'quindecillion';
$groups[18] = 'sexdecillion';
$groups[19] = 'septendecillion';
$groups[20] = 'octodecillion';
$groups[21] = 'novemdecillion';
$groups[22] = 'vigintillion';
$groups[23] = 'unvigintillion';
$groups[24] = 'duovigintillion';
$groups[25] = 'trevigintillion';
$groups[26] = 'quattuorvigintillion';
$groups[27] = 'quinvigintillion';
$groups[28] = 'sexvigintillion';
$groups[29] = 'septenvigintillion';
$groups[30] = 'octovigintillion';
$groups[31] = 'novemvigintillion';
$groups[32] = 'trigintillion';
$groups[33] = 'untrigintillion';
$groups[34] = 'duotrigintillion';
// ***************
// ***************
for($i=0; $i < $DigitsCount; $i++)
{
$DigitGroupsStr .= substr($BigInt,$i,1);
if (($i+1) % 3 == 0) {$DigitGroupsStr .= ' ';}
}
$DigitGroupsStr = trim(StrRev($DigitGroupsStr));
$DigitGroupsCount = 1 + Substr_Count($DigitGroupsStr, ' ');
// Get top name.
$TopNameStr = $groups[$DigitGroupsCount];
// Make number into decimal value (x).
$w = StrRev($DigitGroupsStr);
$n = StrRev(StrRChr($w, ' '));
$L = StrLen($n);
$w = StrRev($w);
$w = trim($n).'.'.substr(Str_Replace(' ','',$w), $L-1, StrLen($w));
$w = SPrintF("%1.$decimals" . "f", $w);
unset($groups);
return "$w $TopNameStr";
}
?>