<?php
function sortCardsBySortOrder(Array $cards, $reverse = false): Array {
$changeAce = false;
if (isLowStraight($cards)) {
$reverse = true;
$changeAce = true;
}
$cards = sortCards($cards, $reverse);
if ($changeAce) {
$ace = array_pop($cards);
//rebuild the array with ace first
$tmpArr = [];
$tmpArr['A'.$ace['suite']] = $ace;
foreach ($cards as $card => $details) {
$tmpArr[$card] = $details;
}
$cards = $tmpArr;
}
return $cards;
}
function sortCards(Array $cards, $reverse = false): Array {
uasort($cards, function($a, $b) use($reverse) {
$result = $a['sort'] <=> $b['sort'];
if (!$reverse) {
$result *= -1;
}
if ($result == 0) {
$result = $a['suite'] <=> $b['suite'];
}
return $result;
});
return $cards;
}
function sortCardsBySuite(Array $cards, $reverse = false): Array {
uasort($cards, function($a, $b) use($reverse) {
$result = $a['suite'] <=> $b['suite'];
if ($result == 0) {
$result = $a['sort'] <=> $b['sort'];
}
if (!$reverse) {
$result *= -1;
}
return $result;
});
return $cards;
}
function shuffleCards(Array $cards): Array {
$shuffled = [];
while ($cards) {
$key = array_rand($cards);
$shuffled[$key] = $cards[$key];
unset($cards[$key]);
}
return $shuffled;
}
function dealCards(Array $cards, $num = 1) {
$result = [null, null];
for ($i = 0; $i < $num; $i++) {
$key = array_rand($cards);
$result[1][$key] = $cards[$key];
unset($cards[$key]);
}
$result[0] = $cards;
return $result;
}
function getLargestSuite(Array $cards): Array {
$result = [];
$lastSuite = "";
$streak = [];
foreach ($cards as $card => $details) {
$suite = $details['suite'];
if ($suite != $lastSuite) {
$lastSuite = $suite;
}
$streak[$suite][$card] = [$card => $details];
}
uasort($streak, function ($a, $b) {
$result = count($a) <=> count($b);
if ($result == 0) {
$a = array_map(function ($v) { $s = 0; foreach($v as $x) { $s += $x['sort']; } return $s; }, $a);
$b = array_map(function ($v) { $s = 0; foreach($v as $x) { $s += $x['sort']; } return $s; }, $b);
$result = array_sum($a) <=> array_sum($b);
}
return $result;
});
return array_pop($streak);
}
function getLargestSet(Array $cards): Array {
$result = [];
$lastType = "";
$streak = [];
foreach ($cards as $card => $details) {
$type = substr($card, 0, 1);
if ($type != $lastType) {
$lastType = $type;
}
$streak[$type][$card] = [$card => $details];
}
uasort($streak, function ($a, $b) {
$result = count($a) <=> count($b);
return $result;
});
return array_pop($streak);
}
function groupBySet(Array $cards): Array {
$result = [];
$lastType = "";
$streak = [];
$cards = sortCardsBySortOrder($cards);
foreach ($cards as $card => $details) {
$type = substr($card, 0, 1);
if ($type != $lastType) {
$lastType = $type;
}
$streak[$type][$card] = [$card => $details];
}
uasort($streak, function ($a, $b) {
$result = count($a) <=> count($b);
return $result * -1;
});
$cards = [];
foreach ($streak as $streaks) {
foreach($streaks as $card => $details) {
$cards[$card] = reset($details);
}
}
return $cards;
}
function isStraightFlush(Array $cards): bool {
// straight flush
return isStraight($cards) && isFlush($cards);
}
function isQuads(Array $cards): bool {
// quads
$hand = sortCardsBySortOrder($cards);
$hand = getLargestSet($hand);
return count($hand) == 4;
}
function isFullHouse(Array $cards): bool {
// full house
return isPair($cards) && isTrips($cards);
}
function isFlush(Array $cards) {
// flush
$hand = sortCardsBySortOrder($cards);
$hand = sortCardsBySuite($hand);
$largest = getLargestSuite($cards);
if (count($largest) == 5) {
return true;
}
return false;
}
function isLowStraight(Array $cards): bool {
// Check for special case where Ace is low
$cards = sortCards($cards, true);
$lowStraight = ["2", "3", "4", "5", "A"];
$tmpArr = [];
$hasAce = false;
// check if ace is there
foreach ($cards as $card => $details) {
if (substr($card, 0, 1) === "A") {
$hasAce = true;
}
}
if ($hasAce) {
$tmpArr[] = "A";
}
foreach (array_slice($cards, 0, 4) as $card => $details) {
$tmpArr[] = substr($card, 0, 1);
}
sort($tmpArr);
if ($tmpArr === $lowStraight) {
return true;
}
return false;
}
function isStraight(Array $cards) {
// straight
$hand = sortCards($cards);
$h = array_slice($hand, 0, 5);
foreach (traverseCardsByTwo($h) as [$card1, $card2]) {
if ($card2) {
$delta = $card1['sort'] - $card2['sort'];
if ($delta !== 1) {
if (isLowStraight($hand)) {
return true;
}
return false;
}
}
}
return true;
}
function isTrips(Array $cards): bool {
// trips
$hand = sortCardsBySortOrder($cards);
$hand = getLargestSet($hand);
return count($hand) == 3;
}
function isTwoPair(Array $cards): bool {
// pair
$result = [];
$lastType = "";
$streak = [];
$pairs = 0;
foreach ($cards as $card => $details) {
$type = substr($card, 0, 1);
if ($type != $lastType) {
$lastType = $type;
}
$streak[$type][$card] = [$card => $details];
}
uasort($streak, function ($a, $b) {
$result = count($a) <=> count($b);
return $result * -1;
});
foreach($streak as $s) {
if (count($s) == 2) {
$pairs++;
}
}
return $pairs >= 2;
}
function isPair(Array $cards): bool {
// pair
$result = [];
$lastType = "";
$streak = [];
foreach ($cards as $card => $details) {
$type = substr($card, 0, 1);
if ($type != $lastType) {
$lastType = $type;
}
$streak[$type][$card] = [$card => $details];
}
uasort($streak, function ($a, $b) {
$result = count($a) <=> count($b);
return $result * -1;
});
foreach($streak as $s) {
if (count($s) == 2) {
return true;
}
}
return false;
}
function traverseCardsByTwo(Array $cards) {
reset($cards);
while(key($cards) !== null) {
$card1 = current($cards);
$card2 = next($cards);
yield [$card1, $card2];
}
}
function getCardsAsString(Array $cards): String {
$s = [];
foreach ($cards as $card => $details) {
$s[] = $card;
}
return implode(",", $s);
}
function combineHands(Array $hand1, Array $hand2): Array {
foreach ($hand2 as $card => $details) {
$hand1[$card] = $details;
}
return $hand1;
}
function DetermineHand($board, $player) {
$hand = combineHands($board, $player);
$taxonomies = [
"Straight Flush" => ["Straight Flush" => 9],
"Quads" => ["Quads" => 8],
"Full House" => ["Full House" => 7],
"Flush" => ["Flush" => 6],
"Straight" => ["Straight" => 5],
"Trips" => ["Trips" => 4],
"Two Pair" => ["Two Pair" => 3],
"Pair" => ["Pair" => 2],
"High Card" => ["High Card" => 1],
];
$h = sortCardsBySortOrder($hand);
if (isStraightFlush($h)) {
$h = getLargestSuite($h);
$h = array_slice($h, 0, 5);
$handResult = ["t" => $taxonomies["Straight Flush"], "h" => $h];
} elseif (isQuads($h)) {
$h = groupBySet($h);
$h = array_slice($h, 0, 5);
$handResult = ["t" => $taxonomies["Quads"], "h" => $h];
} elseif (isFullHouse($h)) {
$h = groupBySet($h);
$h = array_slice($h, 0, 5);
$handResult = ["t" => $taxonomies["Full House"], "h" => $h];
} elseif (isFlush($h)) {
$h = getLargestSuite($h);
$h = array_slice($h, 0, 5);
$handResult = ["t" => $taxonomies["Flush"], "h" => $h];
} elseif (isStraight($h)) {
$handResult = ["t" => $taxonomies["Straight"], "h" => $h];
} elseif (isTrips($h)) {
$h = groupBySet($h);
$h = array_slice($h, 0, 5);
$handResult = ["t" => $taxonomies["Trips"], "h" => $h];
} elseif (isTwoPair($h)) {
$h = groupBySet($h);
$h = array_slice($h, 0, 5);
$handResult = ["t" => $taxonomies["Two Pair"], "h" => $h];
} elseif (isPair($h)) {
$h = groupBySet($h);
$h = array_slice($h, 0, 5);
$handResult = ["t" => $taxonomies["Pair"], "h" => $h];
} else {
$handResult = ["t" => $taxonomies["High Card"], "h" => $h];
}
return $handResult;
}
function DetermineWinnerByTie($hand1, $hand2) {
// hand score is equal to sum of value plus taxonomy
$s1 = $s2 = 0;
foreach($hand1 as $x) {
$s1 += $x['value'];
}
foreach($hand2 as $x) {
$s2 += $x['value'];
}
return $s1 <=> $s2;
}
function DetermineWinner($hand1, $hand2) {
// hand score is equal to sum of sort order plus taxonomy
if (reset($hand1['t']) == reset($hand2['t'])) {
$result = DetermineWinnerByTie($hand1['h'], $hand2['h']);
} else {
$result = reset($hand1['t']) <=> reset($hand2['t']);
}
return $result;
}
$cards = [
"AS" => ["sort" => 14, "suite" => "S", "value" => 11],
"AC" => ["sort" => 14, "suite" => "C", "value" => 11],
"AD" => ["sort" => 14, "suite" => "D", "value" => 11],
"AH" => ["sort" => 14, "suite" => "H", "value" => 11],
"KS" => ["sort" => 13, "suite" => "S", "value" => 10],
"KC" => ["sort" => 13, "suite" => "C", "value" => 10],
"KD" => ["sort" => 13, "suite" => "D", "value" => 10],
"KH" => ["sort" => 13, "suite" => "H", "value" => 10],
"QS" => ["sort" => 12, "suite" => "S", "value" => 10],
"QC" => ["sort" => 12, "suite" => "C", "value" => 10],
"QD" => ["sort" => 12, "suite" => "D", "value" => 10],
"QH" => ["sort" => 12, "suite" => "H", "value" => 10],
"JS" => ["sort" => 11, "suite" => "S", "value" => 10],
"JC" => ["sort" => 11, "suite" => "C", "value" => 10],
"JD" => ["sort" => 11, "suite" => "D", "value" => 10],
"JH" => ["sort" => 11, "suite" => "H", "value" => 10],
"10S" => ["sort" => 10, "suite" => "S", "value" => 10],
"10C" => ["sort" => 10, "suite" => "C", "value" => 10],
"10D" => ["sort" => 10, "suite" => "D", "value" => 10],
"10H" => ["sort" => 10, "suite" => "H", "value" => 10],
"9S" => ["sort" => 9, "suite" => "S", "value" => 9],
"9C" => ["sort" => 9, "suite" => "C", "value" => 9],
"9D" => ["sort" => 9, "suite" => "D", "value" => 9],
"9H" => ["sort" => 9, "suite" => "H", "value" => 9],
"8S" => ["sort" => 8, "suite" => "S", "value" => 8],
"8C" => ["sort" => 8, "suite" => "C", "value" => 8],
"8D" => ["sort" => 8, "suite" => "D", "value" => 8],
"8H" => ["sort" => 8, "suite" => "H", "value" => 8],
"7S" => ["sort" => 7, "suite" => "S", "value" => 7],
"7C" => ["sort" => 7, "suite" => "C", "value" => 7],
"7D" => ["sort" => 7, "suite" => "D", "value" => 7],
"7H" => ["sort" => 7, "suite" => "H", "value" => 7],
"6S" => ["sort" => 6, "suite" => "S", "value" => 6],
"6C" => ["sort" => 6, "suite" => "C", "value" => 6],
"6D" => ["sort" => 6, "suite" => "D", "value" => 6],
"6H" => ["sort" => 6, "suite" => "H", "value" => 6],
"5S" => ["sort" => 5, "suite" => "S", "value" => 5],
"5C" => ["sort" => 5, "suite" => "C", "value" => 5],
"5D" => ["sort" => 5, "suite" => "D", "value" => 5],
"5H" => ["sort" => 5, "suite" => "H", "value" => 5],
"4S" => ["sort" => 4, "suite" => "S", "value" => 4],
"4C" => ["sort" => 4, "suite" => "C", "value" => 4],
"4D" => ["sort" => 4, "suite" => "D", "value" => 4],
"4H" => ["sort" => 4, "suite" => "H", "value" => 4],
"3S" => ["sort" => 3, "suite" => "S", "value" => 3],
"3C" => ["sort" => 3, "suite" => "C", "value" => 3],
"3D" => ["sort" => 3, "suite" => "D", "value" => 3],
"3H" => ["sort" => 3, "suite" => "H", "value" => 3],
"2S" => ["sort" => 2, "suite" => "S", "value" => 2],
"2C" => ["sort" => 2, "suite" => "C", "value" => 2],
"2D" => ["sort" => 2, "suite" => "D", "value" => 2],
"2H" => ["sort" => 2, "suite" => "H", "value" => 2],
];
$board = $player1 = $player2 = [];
shuffleCards($cards);
[$cards, $player1] = dealCards($cards, 2);
[$cards, $player2] = dealCards($cards, 2);
[$cards, $board] = dealCards($cards, 5);
$board1 = combineHands($board, $player1);
$board2 = combineHands($board, $player2);
$board1 = sortCardsBySortOrder($board1);
$b1 = array_slice($board1, 0, 5);
$board2 = sortCardsBySortOrder($board2);
$b2 = array_slice($board2, 0, 5);
echo "Board: ", getCardsAsString($board), "\n";
echo "Player 1: ", getCardsAsString($player1), "\n";
echo "Player 2: ", getCardsAsString($player2), "\n\n";
$hand1 = DetermineHand($player1, $board);
$hand2 = DetermineHand($player2, $board);
echo "Player 1 has: ", key($hand1['t']), " - ", getCardsAsString($hand1['h']), "\n";
echo "Player 2 has: ", key($hand2['t']), " - ", getCardsAsString($hand2['h']), "\n";
if (($win = DetermineWinner($hand1, $hand2)) == -1) {
echo "Player 2 wins!\n";
} elseif ($win == 1) {
echo "Player 1 wins!\n";
} else {
echo "It's a tie!\n";
}
preferences:
26.24 ms | 402 KiB | 5 Q