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

C語言實戰:模擬賭場 Craps 擲骰子遊戲機率計算

     編輯:關於C語言

引言:從一道經典作業說起

故事得從一位留學生的煩惱講起。某大領導的公子在美國名校攻讀計算機科學,本想潇灑度日、混張文憑回國,卻遭遇嚴厲教授布置的經典作業——模擬賭場經典骰子遊戲 Craps(克拉普斯) 的首輪勝率。無奈之下,領導動用關係,這筆「私活」便落到了筆者頭上。

遊戲規則速覽

Craps 使用兩顆六面骰子,首輪擲骰稱為「Come-out Roll」:

  • 立即獲勝:點數和為 7 或 11(Natural)。
  • 立即失敗:點數和為 2、3 或 12(Craps)。
  • 進入點數階段:其他點數(4、5、6、8、9、10)成為「Point」,後續規則較複雜,本作業僅關注首輪勝負機率。

作業核心需求

  1. 編寫 void diceRoll(int *d1, int *d2) 函數,利用 rand() 產生兩顆獨立骰子的點數(1~6)。
  2. 主程式提示使用者輸入整數種子,初始化亂數產生器。
  3. 模擬 10,000 次 首輪擲骰,統計勝負次數。
  4. 輸出勝負次數與機率,理論值分別為勝 0.2222、負 0.1111。

參考實作(C 語言標準寫法)

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

#define ROLLS 10000

void diceRoll(int *d1, int *d2) {
    *d1 = 1 + rand() % 6;
    *d2 = 1 + rand() % 6;
}

int main(void) {
    unsigned seed;
    int win = 0, lose = 0;

    printf("Enter an integer seed value: ");
    scanf("%u", &seed);
    srand(seed);

    for (int i = 0; i < ROLLS; i++) {
        int d1, d2, sum;
        diceRoll(&d1, &d2);
        sum = d1 + d2;

        if (sum == 7 || sum == 11) win++;
        else if (sum == 2 || sum == 3 || sum == 12) lose++;
    }

    printf("Number of wins: %d\n", win);
    printf("Probability of winning: %.4f\n", (double)win / ROLLS);
    printf("Number of losses: %d\n", lose);
    printf("Probability of losing: %.4f\n", (double)lose / ROLLS);

    return 0;
}

關鍵細節與常見坑點

1. 亂數種子與可重現性

作業要求輸入種子,確保結果可驗證。srand() 僅需呼叫一次,切勿放在迴圈內。

2. 迴圈次數邊界

原始碼片段使用 i <= ROLLS 會多跑一次(10001 次),正確寫法為 i < ROLLS。

3. 機率計算精度

整數相除會截斷,務必轉型為 double 或 float 再除,並以 %.4f 輸出四位小數,方便與理論值對照。

4. 函數職責單一

diceRoll 只負責產生點數,不處理勝負邏輯,符合「單一職責原則」,便於測試與維護。

執行範例

Enter an integer seed value: 1
Number of wins: 2230
Probability of winning: 0.2230
Number of losses: 1098
Probability of losing: 0.1098

Enter an integer seed value: 102
Number of wins: 2258
Probability of winning: 0.2258
Number of losses: 1072
Probability of losing: 0.1072

結果隨種子波動,但隨模擬次數增加會逼近理論值(大數法則)。

延伸思考

  • 若要完整模擬 Craps 後續回合,需引入「Point」狀態機。
  • 可嘗試用 /dev/urandom 或 C11 <random> 取代 rand() 取得更高品質亂數。
  • 統計 100 萬次以上樣本,觀察機率收斂過程,繪製圖表更直觀。

結語

這道看似簡單的作業,實則涵蓋亂數產生、模組化設計、統計模擬、浮點精度等核心觀念。掌握這類「小程式、大概念」的練習,是從寫代碼邁向工程思維的關鍵一步。

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