You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Monte Carlo方法近似概率:卡片结构定义与洗牌实现

卡片结构定义、洗牌实现与Monte Carlo概率模拟

1. 定义卡片结构与花色枚举

首先用枚举表示扑克牌的四种花色,再通过结构体组合花色与点数:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdbool.h>

// 花色枚举
typedef enum {
    HEARTS, DIAMONDS, CLUBS, SPADES
} Suit;

// 卡片结构体
typedef struct {
    Suit suit;
    short rank; // 1=A, 2-10=数字, 11=J,12=Q,13=K
} Card;

2. 随机洗牌函数

采用Fisher-Yates洗牌算法,这是无偏且高效的洗牌方式,能保证每张牌在每个位置的概率均等:

// 洗牌函数:随机打乱卡片数组
void shuffle(Card deck[], int deck_size) {
    // 初始化随机种子,仅需调用一次
    static bool seed_initialized = false;
    if (!seed_initialized) {
        srand(time(NULL));
        seed_initialized = true;
    }

    for (int i = deck_size - 1; i > 0; i--) {
        // 生成0到i的随机索引
        int j = rand() % (i + 1);
        // 交换当前卡片与随机选中的卡片
        Card temp = deck[i];
        deck[i] = deck[j];
        deck[j] = temp;
    }
}

3. Monte Carlo 方法近似概率计算

以**“洗牌后第一张牌为红桃A”**的概率为例,通过多次重复洗牌实验,统计符合条件的次数,用频率近似概率:

实现步骤

  1. 初始化一副完整的扑克牌,标记红桃A的特征;
  2. 重复进行N次洗牌实验(N越大,近似精度越高);
  3. 每次洗牌后检查第一张牌是否为红桃A,统计命中次数;
  4. 最终概率 = 命中次数 / 总实验次数。

代码实现

// 创建一副完整的扑克牌
void create_deck(Card deck[]) {
    int index = 0;
    for (int suit = HEARTS; suit <= SPADES; suit++) {
        for (short rank = 1; rank <= 13; rank++) {
            deck[index].suit = (Suit)suit;
            deck[index].rank = rank;
            index++;
        }
    }
}

int main() {
    const int DECK_SIZE = 52;
    const int NUM_TRIALS = 1000000; // 100万次实验,保证精度
    Card deck[DECK_SIZE];
    int success_count = 0;

    create_deck(deck);

    for (int i = 0; i < NUM_TRIALS; i++) {
        Card temp_deck[DECK_SIZE];
        // 复制原牌组避免每次重新创建
        for (int j = 0; j < DECK_SIZE; j++) {
            temp_deck[j] = deck[j];
        }
        shuffle(temp_deck, DECK_SIZE);
        // 检查第一张是否为红桃A(HEARTS,rank=1)
        if (temp_deck[0].suit == HEARTS && temp_deck[0].rank == 1) {
            success_count++;
        }
    }

    double probability = (double)success_count / NUM_TRIALS;
    printf("Monte Carlo近似概率:%.4f\n", probability);
    printf("理论概率:%.4f\n", 1.0 / 52);

    return 0;
}

说明

  • 实验次数建议设置为10万次以上,次数越多,结果越接近理论值(1/52 ≈ 0.0192);
  • 可以修改统计条件,比如计算“洗牌后出现至少一对相同点数的牌”“同花顺”等复杂事件的概率,只需调整判断逻辑即可。

内容的提问来源于stack exchange,提问作者Mukund

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 19:15:35