首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

C++ 實戰專案:撲克牌模擬系統(洗牌、發牌、排序)

     編輯:關於C++

本專案在記憶體中模擬一副 54 張撲克牌,實作洗牌、發牌、玩家管理與手牌排序功能,展示 C 結構體、指標陣列、動態記憶體管理與演算法應用。

資料結構設計

enum Suit { HEART, SPADE, DIAMOND, CLUB, JOKER_SMALL, JOKER_BIG };
const int CARD_COUNT = 54;

struct Card {
    int value;      // 1=A, 11=J, 12=Q, 13=K, 14=小王, 15=大王
    Suit suit;
};

struct Player {
    char name[64];
    Card** cards;   // 指向原始牌陣列的指標陣列,節省空間
    int cardCount;
};

核心功能實作

1. 初始化牌組

Card g_deck[CARD_COUNT];

void InitDeck() {
    int idx = 0;
    // 52 張一般牌
    for (int i = 0; i < CARD_COUNT - 2; i++) {
        g_deck[idx].value = i / 4 + 1;   // 1~13 循環 4 次
        g_deck[idx].suit = static_cast(i % 4);
        idx++;
    }
    // 兩張王
    g_deck[idx++] = {14, JOKER_SMALL};
    g_deck[idx++] = {15, JOKER_BIG};
}

2. 洗牌演算法

使用 Fisher-Yates 洗牌,隨機交換位置,產生指標陣列避免移動實際 Card 結構。

Card** Shuffle() {
    Card** shuffled = new Card*[CARD_COUNT];
    Card** temp = new Card*[CARD_COUNT];
    for (int i = 0; i < CARD_COUNT; i++) temp[i] = &g_deck[i];

    for (int i = 0; i < CARD_COUNT; i++) {
        int r = rand() % CARD_COUNT;
        while (temp[r] == nullptr) r = (r + 1) % CARD_COUNT; // 找下一張未用
        shuffled[i] = temp[r];
        temp[r] = nullptr;
    }
    delete[] temp;
    return shuffled;
}

3. 發牌邏輯

void Deal(Player** players, int playerCount, Card** shuffled) {
    int cardsPerPlayer = CARD_COUNT / playerCount + 1;
    for (int i = 0; i < playerCount; i++) {
        players[i]->cards = new Card*[cardsPerPlayer];
        players[i]->cardCount = 0;
    }
    for (int i = 0; i < CARD_COUNT; i++) {
        Player* p = players[i % playerCount];
        p->cards[p->cardCount++] = shuffled[i];
    }
}

4. 手牌排序

支援自訂比較函數(升序/降序),使用氣泡排序教學示意。

typedef int (*CompareFunc)(Card*, Card*);

void SortHand(Card** hand, int count, CompareFunc cmp) {
    for (int i = 0; i < count - 1; i++)
        for (int j = 0; j < count - i - 1; j++)
            if (cmp(hand[j], hand[j+1])) {
                Card* tmp = hand[j];
                hand[j] = hand[j+1];
                hand[j+1] = tmp;
            }
}

// 升序:先比點數,再比花色
int CompareAsc(Card* a, Card* b) {
    if (a->value != b->value) return a->value > b->value;
    return a->suit > b->suit;
}

// 降序
int CompareDesc(Card* a, Card* b) {
    if (a->value != b->value) return a->value < b->value;
    return a->suit < b->suit;
}

5. 牌面顯示

char* GetCardName(const Card* c) {
    static const char* suits[] = {"紅桃", "黑桃", "方塊", "梅花"};
    static const char* values[] = {"", "A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "小王", "大王"};
    
    char* name = new char[16];
    if (c->value >= 14) // 王
        sprintf(name, "%s", values[c->value]);
    else
        sprintf(name, "%s%s", suits[c->suit], values[c->value]);
    return name; // 呼叫端需 delete[]
}

主程式流程

int main() {
    srand(time(nullptr));
    InitDeck();
    Card* shuffled = Shuffle();

    Player p1{"隔壁老王"}, p2{"小明"}, p3{"田中龜孫"};
    Player* players[] = {&p1, &p2, &p3};

    Deal(players, 3, shuffled);
    delete[] shuffled;

    for (auto p : players) {
        cout << p->name << ": ";
        SortHand(p->cards, p->cardCount, CompareAsc);
        for (int i = 0; i < p->cardCount; i++) {
            char* name = GetCardName(p->cards[i]);
            cout << name << ' ';
            delete[] name;
        }
        cout << endl;
        delete[] p->cards;
    }
    return 0;
}

執行結果範例

隔壁老王: 梅花A 方塊2 紅桃3 黑桃4 ...
小明: 方塊A 梅花2 黑桃3 紅桃4 ...
田中龜孫: 黑桃A 紅桃2 梅花3 方塊4 ...

專案展示了指標陣列管理物件、回調函數實現策略模式、動態記憶體分配釋放等核心 C/C++ 技能。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved