<?php
const CARDS = [
'2' => 2
, '3' => 3
, '4' => 4
, '5' => 5
, '6' => 6
, '7' => 7
, '8' => 8
, '9' => 9
, '10' => 10
, 'J' => 11
, 'Q' => 12
, 'K' => 13
, 'A' => 14
];
const HIGH_CARD = 'high card';
const PAIR = 'pair';
const STRAIGHT = 'straight';
const THREE_CARD = 'three card';
const HAND_RANKS = [
'high card' => 0
,'pair' => 1
,'straight' => 2
,'three card' => 3
];
function showDown (string $card11, string $card12, string $card13, string $card21, string $card22, string $card23): array
{
$cards = [$card11, $card12, $card13, $card21, $card22, $card23];
$cardRanks = [];
// 6枚のカードの文字列から数字部分のみを抽出し、新しい配列$cardNumbersに格納
// その後、CARDS定数を使って数字ごとのランクに変換
foreach ($cards as $card) {
array_push($cardRanks, CARDS[substr($card, 1)]);
}
// 3つずつ各プレイヤーの手札として振り分ける
$playerCardRanks = array_chunk($cardRanks, 3);
// プレイヤーごとの役をユーザー定義関数checkHandsで決定。
// $playerCardRanksを2プレイヤー分に分けてからでないと、checkHands関数で2次元配列を扱うことになってしまう上に、配列の引数2つというのも関数を定義しづらい
$player1Hand = checkHands($playerCardRanks[0]);
$player2Hand = checkHands($playerCardRanks[1]);
// 勝敗を決定
$winner = decideWinner($player1Hand, $player2Hand);
return [$player1Hand['hand'], $player2Hand['hand'], $winner];
}
function checkHands(array $playerCardRanks): array
{
$hand = HIGH_CARD;
if (isThreeCard($playerCardRanks)) {
$hand = THREE_CARD;
} elseif (isPair($playerCardRanks)) {
$hand = PAIR;
} elseif (isStraight($playerCardRanks)) {
$hand = STRAIGHT;
}
rsort($playerCardRanks);
// 手札がa,2,3の場合はaを最弱にする
// aのランク14をカードの種類の数13で割った余りは1なので、それをaのランクとする
if ($playerCardRanks[1] === $playerCardRanks[2] + 1 && $playerCardRanks[2] === $playerCardRanks[0] % count(CARDS) + 1) {
$playerCardRanks[0] = $playerCardRanks[0] % count(CARDS);
}
return [
'hand' => $hand
,'handRank' => HAND_RANKS[$hand]
,'biggestNum' => $playerCardRanks[0]
,'middleNum' => $playerCardRanks[1]
,'smallestNum' => $playerCardRanks[2]
];
}
function isThreeCard(array $playerCardRanks): bool
{
// 一つ目の値の数がカード全体の枚数に等しいとき(すなわち、全てのカードの値が同じとき)、trueを返す(ボツ案)
// if (array_count_values($playerCardRanks)[0] === count($playerCardRanks)) {
// return true;
// それぞれのプレイヤーの手札のうち、重複する種類が1種類の(すべて重複する)ときにtrueを返す
if (count(array_unique($playerCardRanks)) === 1) {
return true;
} else {
return false;
}
// ここは無難に、それぞれのカードの値が等しいときでも可
// if ($playerCardRanks[0] === $playerCardRanks[1] && $playerCardRanks[1] === $playerCardRanks[2]) {
// return true;
// }
}
function isPair(array $playerCardRanks): bool
{
// if (count(array_count_values($playerCardRanks)) === 2) {
// return true; (ボツ案)
// 重複する値の種類が2の時
if (count(array_unique($playerCardRanks)) === 2) {
return true;
} else {
return false;
}
}
function isStraight(array $playerCardRanks): bool
{
rsort($playerCardRanks);
$biggestCard = $playerCardRanks[0];
$middleCard = $playerCardRanks[1];
$smallestCard = $playerCardRanks[2];
// echo('biggestCard:' . $biggestCard);
// 1番大きい数が2番目の数より1大きく、2番目の数が3番目の数より大きい場合
if ($biggestCard === $middleCard + 1 && $middleCard === $smallestCard + 1) {
return true;
// 1番大きい数がA、2番目の数が3、1番小さい数が2の場合を想定している。
// AのCardRank14をカードの種類の数13で割った余りは1なので、AのCardRankをそれにすり替える。(リングバッファーのアルゴリズムから着想。)
} elseif ($middleCard === $smallestCard + 1 && $smallestCard === $biggestCard % count(CARDS) + 1) {
return true;
} else {
return false;
}
}
function decideWinner (array $player1Hand, array $player2Hand): int
{
// 勝敗を決める要素をまとめる。それぞれの役、1番大きい数、2番目の数、1番小さい数
$judgementElements = ['handRank', 'biggestNum', 'middleNum', 'smallestNum'];
// それぞれの要素ごとに大小を比較していって、大小が決まった時点で結果を返す
// いずれの要素でも決着がつかなかった場合に、0(引き分け)を返す
foreach ($judgementElements as $judgementElement) {
if($player1Hand[$judgementElement] > $player2Hand[$judgementElement]) {
return 1;
} elseif ($player2Hand[$judgementElement] > $player1Hand[$judgementElement]) {
return 2;
}
}
return 0;
}
var_dump(showDown('SK', 'D9', 'CJ', 'S10', 'H10', 'D6'));
var_dump(showDown('DK', 'S2', 'HA', 'C4', 'H5', 'S6'));
var_dump(showDown('S9', 'CJ', 'DK', 'C3', 'C3', 'H3'));
var_dump(showDown('H3', 'D4', 'C5', 'HK', 'S10', 'DK'));
var_dump(showDown('S3', 'H3', 'C3', 'D10', 'SK', 'D10'));
var_dump(showDown('C3', 'S3', 'H3', 'CK', 'SJ', 'SQ'));
var_dump(showDown('DJ', 'HK', 'S9', 'CQ', 'D9', 'S10'));
var_dump(showDown('C7', 'S5', 'H3', 'S5', 'S7', 'D3'));
var_dump(showDown('CA', 'DA', 'CK', 'D2', 'D2', 'C3'));
var_dump(showDown('HK', 'DK', 'SA', 'CA', 'SA', 'SK'));
var_dump(showDown('D4', 'D7', 'K7', 'D6', 'K4', 'C6'));
var_dump(showDown('SK', 'D9', 'CJ', 'S10', 'H10', 'D6'));
var_dump(showDown('S4', 'C4', 'S7', 'S4', 'S4', 'C7'));
var_dump(showDown('SA', 'DQ', 'DK', 'CA', 'C2', 'D3'));
var_dump(showDown('SA', 'DK', 'DQ', 'CK', 'CQ', 'DJ'));
var_dump(showDown('H2', 'D3', 'D4', 'HA', 'C2', 'S3'));
var_dump(showDown('S2', 'S3', 'S4', 'C2', 'C3', 'D4'));
var_dump(showDown('S2', 'S2', 'S2', 'DA', 'HA', 'CA'));
var_dump(showDown('CK', 'CK', 'SK', 'SA', 'HA', 'DA'));
var_dump(showDown('D2', 'C2', 'S2', 'C3', 'H3', 'S3'));