1 条题解
-
0
桥牌发牌与排序问题题解
一、题目分析
题目要求模拟桥牌游戏的发牌和排序过程,具体规则如下:
- 玩家顺序:北(N)、东(E)、南(S)、西(W),按顺时针方向发牌。
- 花色排序:梅花(C) < 方块(D) < 黑桃(S) < 红桃(H)。
- 牌面等级:2 < 3 < ... < 10(T) < J < Q < K < A。
- 发牌规则:从指定发牌人左侧玩家开始,按顺时针方向发完52张牌。
- 输出格式:按南、西、北、东顺序输出每位玩家的手牌,每张牌用特定格式展示。
二、算法思路
- 输入处理:读取发牌人及牌组字符串,解析每张牌的花色和牌面。
- 发牌模拟:根据发牌人确定起始玩家,按顺时针方向依次发牌。
- 排序规则:先按花色排序,再按牌面等级排序。
- 输出格式化:按指定格式输出每位玩家的手牌。
三、代码实现
#include <iostream> #include <cstdio> #include <algorithm> #include <string> #include <cstring> using namespace std; // 定义花色和牌面的排序依据 string suitOrder = "CDSH"; // 花色排序:梅花 < 方块 < 黑桃 < 红桃 string rankOrder = "23456789TJQKA"; // 牌面排序:2 < 3 < ... < A // 存储每张牌的信息 struct Card { char suit; // 花色 char rank; // 牌面 int suitIdx; // 花色的排序索引 int rankIdx; // 牌面的排序索引 }; // 比较函数:先按花色排序,再按牌面排序 bool compareCards(const Card& a, const Card& b) { if (a.suitIdx != b.suitIdx) return a.suitIdx < b.suitIdx; return a.rankIdx < b.rankIdx; } int main() { string dealer; while (cin >> dealer) { if (dealer == "#") break; // 输入结束标志 // 确定发牌人在玩家顺序中的索引 (N=0, E=1, S=2, W=3) int dealerIdx = string("NESW").find(dealer); int currentPlayer = (dealerIdx + 1) % 4; // 从发牌人的下一位开始发牌 // 存储四位玩家的手牌 Card players[4][13]; int count[4] = {0}; // 记录每位玩家已拿到的牌数 // 读取两行星号分隔的牌组 for (int line = 0; line < 2; ++line) { string cardsLine; cin >> cardsLine; // 每两个字符解析为一张牌 for (int i = 0; i < cardsLine.size(); i += 2) { char suit = cardsLine[i]; char rank = cardsLine[i+1]; // 创建牌对象并设置排序索引 Card card; card.suit = suit; card.rank = rank; card.suitIdx = suitOrder.find(suit); card.rankIdx = rankOrder.find(rank); // 发给当前玩家 players[currentPlayer][count[currentPlayer]++] = card; currentPlayer = (currentPlayer + 1) % 4; // 顺时针轮到下一位玩家 } } // 对每位玩家的手牌进行排序 for (int i = 0; i < 4; ++i) { sort(players[i], players[i] + 13, compareCards); } // 输出顺序:南(2)、西(3)、北(0)、东(1) int outputOrder[4] = {2, 3, 0, 1}; string playerNames[4] = {"South", "West", "North", "East"}; for (int i = 0; i < 4; ++i) { int playerIdx = outputOrder[i]; cout << playerNames[i] << " player:" << endl; cout << "+---+---+---+---+---+---+---+---+---+---+---+---+---+" << endl; // 输出第一行:牌面+空格+牌面 cout << "|"; for (int j = 0; j < 13; ++j) { cout << players[playerIdx][j].rank << " " << players[playerIdx][j].rank << "|"; } cout << endl; // 输出第二行:空格+花色+空格 cout << "|"; for (int j = 0; j < 13; ++j) { cout << " " << players[playerIdx][j].suit << " |"; } cout << endl; // 输出第三行:牌面+空格+牌面 cout << "|"; for (int j = 0; j < 13; ++j) { cout << players[playerIdx][j].rank << " " << players[playerIdx][j].rank << "|"; } cout << endl; cout << "+---+---+---+---+---+---+---+---+---+---+---+---+---+" << endl; } cout << endl; // 每组输出后有一个空行 } return 0; }
四、代码解释
-
数据结构:
Card
结构体存储每张牌的花色、牌面及对应的排序索引。suitOrder
和rankOrder
定义排序规则。
-
发牌逻辑:
- 根据输入的发牌人确定起始玩家索引。
- 依次读取两行星号分隔的牌组,按顺时针方向分配给玩家。
-
排序处理:
- 使用
sort
函数和自定义比较函数对每位玩家的手牌进行排序。
- 使用
-
输出格式化:
- 按南、西、北、东的顺序输出每位玩家的手牌。
- 每张牌用三行格式展示,符合题目要求的视觉效果。
五、复杂度分析
- 时间复杂度:排序每位玩家的手牌需要O(13 log 13),总体为O(4 × 13 log 13) = O(52 log 13),约等于O(180),非常高效。
- 空间复杂度:存储所有玩家的手牌需要O(4 × 13) = O(52),即52张牌的空间。
该算法通过合理的数据结构和排序策略,简洁高效地完成了桥牌发牌和排序任务。
- 1
信息
- ID
- 787
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 3
- 已通过
- 1
- 上传者