class Card { private const SPADE = 1; private const HEART = 2; private const CLUB = 3; private const DIAMOND = 4; private const JOKER = 5; // 大小王 private const WILD = 6; // 通配牌

private const CARD_VALUES = [ // 牌值对应的数字
    "A" => 1,
    "2" => 2,
    "3" => 3,
    "4" => 4,
    "5" => 5,
    "6" => 6,
    "7" => 7,
    "8" => 8,
    "9" => 9,
    "10" => 10,
    "J" => 11,
    "Q" => 12,
    "K" => 13,
];

private const CARD_VALUES_REVERSE = [ // 数字对应的牌值
    1 => "A",
    2 => "2",
    3 => "3",
    4 => "4",
    5 => "5",
    6 => "6",
    7 => "7",
    8 => "8",
    9 => "9",
    10 => "10",
    11 => "J",
    12 => "Q",
    13 => "K",
];

private const CARD_NUMS = [ // 牌编码对应的花色和牌值
    1 => ["suit" => self::SPADE, "value" => "A"],
    2 => ["suit" => self::SPADE, "value" => "2"],
    3 => ["suit" => self::SPADE, "value" => "3"],
    4 => ["suit" => self::SPADE, "value" => "4"],
    5 => ["suit" => self::SPADE, "value" => "5"],
    6 => ["suit" => self::SPADE, "value" => "6"],
    7 => ["suit" => self::SPADE, "value" => "7"],
    8 => ["suit" => self::SPADE, "value" => "8"],
    9 => ["suit" => self::SPADE, "value" => "9"],
    10 => ["suit" => self::SPADE, "value" => "10"],
    11 => ["suit" => self::SPADE, "value" => "J"],
    12 => ["suit" => self::SPADE, "value" => "Q"],
    13 => ["suit" => self::SPADE, "value" => "K"],
    14 => ["suit" => self::HEART, "value" => "A"],
    15 => ["suit" => self::HEART, "value" => "2"],
    16 => ["suit" => self::HEART, "value" => "3"],
    17 => ["suit" => self::HEART, "value" => "4"],
    18 => ["suit" => self::HEART, "value" => "5"],
    19 => ["suit" => self::HEART, "value" => "6"],
    20 => ["suit" => self::HEART, "value" => "7"],
    21 => ["suit" => self::HEART, "value" => "8"],
    22 => ["suit" => self::HEART, "value" => "9"],
    23 => ["suit" => self::HEART, "value" => "10"],
    24 => ["suit" => self::HEART, "value" => "J"],
    25 => ["suit" => self::HEART, "value" => "Q"],
    26 => ["suit" => self::HEART, "value" => "K"],
    27 => ["suit" => self::CLUB, "value" => "A"],
    28 => ["suit" => self::CLUB, "value" => "2"],
    29 => ["suit" => self::CLUB, "value" => "3"],
    30 => ["suit" => self::CLUB, "value" => "4"],
    31 => ["suit" => self::CLUB, "value" => "5"],
    32 => ["suit" => self::CLUB, "value" => "6"],
    33 => ["suit" => self::CLUB, "value" => "7"],
    34 => ["suit" => self::CLUB, "value" => "8"],
    35 => ["suit" => self::CLUB, "value" => "9"],
    36 => ["suit" => self::CLUB, "value" => "10"],
    37 => ["suit" => self::CLUB, "value" => "J"],
    38 => ["suit" => self::CLUB, "value" => "Q"],
    39 => ["suit" => self::CLUB, "value" => "K"],
    40 => ["suit" => self::DIAMOND, "value" => "A"],
    41 => ["suit" => self::DIAMOND, "value" => "2"],
    42 => ["suit" => self::DIAMOND, "value" => "3"],
    43 => ["suit" => self::DIAMOND, "value" => "4"],
    44 => ["suit" => self::DIAMOND, "value" => "5"],
    45 => ["suit" => self::DIAMOND, "value" => "6"],
    46 => ["suit" => self::DIAMOND, "value" => "7"],
    47 => ["suit" => self::DIAMOND, "value" => "8"],
    48 => ["suit" => self::DIAMOND, "value" => "9"],
    49 => ["suit" => self::DIAMOND, "value" => "10"],
    50 => ["suit" => self::DIAMOND, "value" => "J"],
    51 => ["suit" => self::DIAMOND, "value" => "Q"],
    52 => ["suit" => self::DIAMOND, "value" => "K"],
    53 => ["suit" => self::JOKER, "value" => ""],
    54 => ["suit" => self::JOKER, "value" => ""],
    55 => ["suit" => self::WILD, "value" => "2"],
    56 => ["suit" => self::WILD, "value" => "2"],
    57 => ["suit" => self::WILD, "value" => "2"],
    58 => ["suit" => self::WILD, "value" => "2"],
    59 => ["suit" => self::WILD, "value" => "2"],
    60 => ["suit" => self::WILD, "value" => "2"],
    61 => ["suit" => self::WILD, "value" => "2"],
    62 => ["suit" => self::WILD, "value" => "2"],
    63 => ["suit" => self::JOKER, "value" => ""],
    64 => ["suit" => self::JOKER, "value" => ""],
];

private static function getCardValue(int $cardNum): string
{
    return self::CARD_NUMS[$cardNum]["value"];
}

private static function getCardSuit(int $cardNum): int
{
    return self::CARD_NUMS[$cardNum]["suit"];
}

/**
 * 获取n副牌的全部编码
 * @param int $n 几副牌 大于0的正整数
 * @param bool $useJoker 是否有王
 * @return array 根据参数返回n副牌的全部编码
 */
public function getAllCardNumSet(int $n, bool $useJoker): array
{
    $cardNums = [];
    for ($i = 1; $i <= $n; $i++) {
        $start = ($i - 1) * 64 + 1;
        $end = $i * 64;
        for ($j = $start; $j <= $end; $j++) {
            if (!$useJoker && ($j == 53 || $j == 54)) {
                continue;
            }
            $cardNums[] = $j;
        }
    }
    return $cardNums;
}

/**
 * 对输入的牌进行排序
 * @param array $input 不重复整数的一维数组,即getAllCardNumSet()的子集
 * @return array 返回最长同花色排序结果的一维数组
 */
public function sortCards(array $input): array
{
    $suits = []; // 存储每个花色的牌
    foreach ($input as $cardNum) {
        $suit = self::getCardSuit($cardNum);
        if (!isset($suits[$suit])) {
            $suits[$suit] = [];
        }
        $suits[$suit][] = $cardNum;
    }

    $longestSuit = [];
    $longestSuitLength = 0;
    foreach ($suits as $suit => $cards) {
        $sortedCards = $this->sortSuit($cards);
        $length = count($sortedCards);
        if ($length > $longestSuitLength) {
            $longestSuit = $sortedCards;
            $longestSuitLength = $length;
        }
    }

    return $longestSuit;
}

/**
 * 对同一花色的牌进行排序
 * @param array $cards 同一花色的牌
 * @return array 排序后的牌
 */
private function sortSuit(array $cards): array
{
    $values = []; // 存储每个牌值的牌
    $wilds = []; // 存储每个缺口对应的通配牌
    $wildCount = 0; // 通配牌数量
    foreach ($cards as $cardNum) {
        $value = self::getCardValue($cardNum);
        if (!isset($values[$value])) {
            $values[$value] = [];
        }
        $values[$value][] = $cardNum;
    }

    // 排序牌值
    uksort($values, function ($value1, $value2) {
        // 牌值为A的处理
        if ($value1 == "A") {
            $value1 = 1;
        }
        if ($value2 == "A") {
            $value2 = 1;
        }
        // 牌值为2的处理
        if ($value1 == "2") {
            $value1 = 14;
        }
        if ($value2 == "2") {
            $value2 = 14;
        }
        // 其他牌值的处理
        $value1Num = self::CARD_VALUES[$value1];
        $value2Num = self::CARD_VALUES[$value2];
        if ($value1Num == $value2Num) {
            return 0;
        }
        return $value1Num < $value2Num ? -1 : 1;
    });

    $sortedCards = [];
    $wildUsed = []; // 记录已经使用过的通配牌
    foreach ($values as $value => $cards) {
        $wildCount -= count($wilds); // 已经使用的通配牌数量减去当前缺口数量
        $wilds = []; // 清空缺口和通配牌
        $missing = []; // 存储当前缺口
        $prevCardNum = null;
        foreach ($cards as $cardNum) {
            if ($prevCardNum !== null && self::getCardValue($cardNum) != self::getCardValue($prevCardNum)) {
                if (count($missing) > $wildCount) {
                    break; // 通配牌不足以填补所有缺口,退出循环
                }
                // 填补缺口
                $missingCount = count($missing);
                for ($i = 0; $i < $missingCount; $i++) {
                    $wild = array_shift($wilds);
                    if (!in_array($wild, $wildUsed)) {
                        $wildUsed[] = $wild;
                        $sortedCards[] = $wild;
                    }
                }
                $missing = [];
            }

            $suit = self::getCardSuit($cardNum);
            $value = self::getCardValue($cardNum);
            if ($value == "2") {
                $wilds[] = $cardNum; // 记录缺口和通配牌
            } else {
                if (count($missing) > 0) { // 有缺口
                    $wild = array_shift($wilds);
                    if (!in_array($wild, $wildUsed)) {
                        $wildUsed[] = $wild;
                        $sortedCards[] = $wild;
                    }
                }
                $missing = [];
                $sortedCards[] = $cardNum;
            }

            $prevCardNum = $cardNum;
            if (self::getCardValue($cardNum) != "K") { // 记录缺口
                $missingSuit = $suit;
                $missingValueNum = self::CARD_VALUES[self::getCardValue($cardNum)] + 1;
                $missingValue = self::CARD_VALUES_REVERSE[$missingValueNum] ?? null;
                if ($missingValue !== nul
php 题目说明及要求: - 请使用面向对象思维答题且不要依赖枚举 - 禁止出现notice请自行修改phpini不要屏蔽错误输出 扑克牌编码规则如下: - 使用从1开始的十进制整数为每张扑克牌进行编码 - 花色顺序:黑桃红桃梅花方块 - 每副牌占用64个数字如1-6465-128以此类推;每个花色占用16个数字但实际使用了13个如1-13是黑桃A到K17-29是红桃A到K以此类推;

原文地址: http://www.cveoy.top/t/topic/ckH0 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录