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

Blackjack概率计算C语言代码纠错求助:实验逻辑问题排查

问题分析与代码修正

原代码核心错误点

  • 未初始化变量aftersum:int aftersum=sum+k;定义时sum和k未赋值,为垃圾数据,导致后续循环判断完全失效。
  • 错误的成功判定逻辑:当首次抽牌和小于目标时,无论后续抽牌是否超过目标,都直接判定成功并累加统计,违背题目“超过目标则失败”的规则。
  • Ace处理漏洞:初始两张牌的Ace转换逻辑不严谨,后续抽牌的Ace处理未正确结合当前总和判断。
  • 概率与牌数计算错误:概率计算未按总实验次数100000次换算百分比;成功平均用牌数错误除以总实验次数,而非成功次数。
  • 缺失失败分支处理:未处理首次抽牌和超过目标的失败场景,导致成功次数统计虚高。

修正后的代码

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

int main(void) {
    // 初始化随机数种子,保证每次运行结果不同
    srand((unsigned int)time(NULL));

    printf("Points  Probability  #Cards\n");
    // 遍历4到21的所有目标点数
    for (int points = 4; points <= 21; points++) {
        int count = 0;          // 当前目标的实验次数
        unsigned int total = 0; // 成功次数
        unsigned int cardsum = 0; // 成功实验的总用牌数

        // 执行100000次实验
        while (count < 100000) {
            count++;
            int sum = 0;
            int card_count = 0;

            // 抽取初始两张牌
            for (int i = 0; i < 2; i++) {
                int card = rand() % 13 + 1;
                // 转换牌面:J/Q/K为10,Ace暂按11计算(后续调整)
                if (card > 10) {
                    card = 10;
                } else if (card == 1) {
                    card = 11;
                }
                sum += card;
                card_count++;
            }

            // 处理两张Ace的特殊情况:11+11=22,自动转为1+11=12
            if (sum == 22) {
                sum = 12;
            }

            // 首次抽牌结果判断
            if (sum > points) {
                // 超过目标,实验失败,跳过统计
                continue;
            } else if (sum == points) {
                // 恰好等于目标,成功
                total++;
                cardsum += card_count;
                continue;
            }

            // 总和小于目标,继续抽牌直到结果明确
            while (sum < points) {
                int card = rand() % 13 + 1;
                if (card > 10) {
                    card = 10;
                } else if (card == 1) {
                    // Ace智能转换:加11不超目标则用11,否则用1
                    card = (sum + 11) <= points ? 11 : 1;
                }
                sum += card;
                card_count++;

                // 抽牌后超过目标,实验失败,终止抽牌
                if (sum > points) {
                    break;
                }
            }

            // 循环结束后判断是否成功
            if (sum == points) {
                total++;
                cardsum += card_count;
            }
        }

        // 计算成功概率(百分比)和成功时的平均用牌数
        float percent = (float)total / 100000.0 * 100;
        float avg_cards = (float)cardsum / total; // 仅除以成功次数

        printf("  %2d      %5.2f%%      %.2f\n", points, percent, avg_cards);
    }
    return 0;
}

关键修正说明

  1. 随机数种子初始化:添加srand((unsigned int)time(NULL)),避免每次运行生成相同的随机牌序列。
  2. 严谨的胜负判定:
    • 首次抽牌超过目标直接标记失败,不参与成功统计。
    • 后续抽牌若超过目标,立即终止抽牌并标记失败,仅当总和恰好等于目标时计入成功。
  3. 优化Ace处理:
    • 两张Ace自动调整为12,避免初始总和22的无效情况。
    • 后续抽Ace时,根据当前总和动态选择1或11,确保不提前超过目标。
  4. 修正统计逻辑:
    • 成功概率按(成功次数/总实验次数)*100计算,正确转换为百分比。
    • 成功平均用牌数为成功总用牌数/成功次数,解决了目标点数4时结果异常的问题。
  5. 清晰的牌数统计:用card_count直接记录单次实验的用牌数,成功时累加至cardsum,逻辑直观不易出错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 20:30:46