php 题目说明及要求: - 请使用面向对象思维答题且不要依赖枚举 - 禁止出现notice请自行修改phpini不要屏蔽错误输出 扑克牌编码规则如下: - 使用从1开始的十进制整数为每张扑克牌进行编码 - 花色顺序:黑桃红桃梅花方块 - 每副牌占用64个数字如1-6465-128以此类推;每个花色占用16个数字但实际使用了13个如1-13是黑桃A到K17-29是红桃A到K以此类推;
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
原文地址: http://www.cveoy.top/t/topic/ckH0 著作权归作者所有。请勿转载和采集!