1 条题解

  • 0
    @ 2025-5-27 20:48:36

    桥牌发牌与排序问题题解

    一、题目分析

    题目要求模拟桥牌游戏的发牌和排序过程,具体规则如下:

    1. 玩家顺序:北(N)、东(E)、南(S)、西(W),按顺时针方向发牌。
    2. 花色排序:梅花(C) < 方块(D) < 黑桃(S) < 红桃(H)。
    3. 牌面等级:2 < 3 < ... < 10(T) < J < Q < K < A。
    4. 发牌规则:从指定发牌人左侧玩家开始,按顺时针方向发完52张牌。
    5. 输出格式:按南、西、北、东顺序输出每位玩家的手牌,每张牌用特定格式展示。

    二、算法思路

    1. 输入处理:读取发牌人及牌组字符串,解析每张牌的花色和牌面。
    2. 发牌模拟:根据发牌人确定起始玩家,按顺时针方向依次发牌。
    3. 排序规则:先按花色排序,再按牌面等级排序。
    4. 输出格式化:按指定格式输出每位玩家的手牌。

    三、代码实现

    #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;
    }
    

    四、代码解释

    1. 数据结构

      • Card结构体存储每张牌的花色、牌面及对应的排序索引。
      • suitOrderrankOrder定义排序规则。
    2. 发牌逻辑

      • 根据输入的发牌人确定起始玩家索引。
      • 依次读取两行星号分隔的牌组,按顺时针方向分配给玩家。
    3. 排序处理

      • 使用sort函数和自定义比较函数对每位玩家的手牌进行排序。
    4. 输出格式化

      • 按南、西、北、东的顺序输出每位玩家的手牌。
      • 每张牌用三行格式展示,符合题目要求的视觉效果。

    五、复杂度分析

    • 时间复杂度:排序每位玩家的手牌需要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
    上传者