C 語言初學教材 - 第四章 模擬勝負

擲骰子遊戲有可能贏,有可能輸,也有可能平手,各種可能情況如下表

1, 12, 13, 14, 15, 16, 1
1, 22, 23, 24, 25, 56, 2
1, 32, 33, 34, 35, 36, 3
1, 42, 43, 44, 45, 46, 4
1, 52, 53, 54, 55, 56, 5
1, 62, 63, 64, 65, 66, 6


平手的情況有 6 種,贏的情況有 0 + 1 + 2 + 3 + 4 + 5 = 15 種,輸的情況也有 15 種,所有的情況有 36 種,因此理論上,平手的機率為 6 / 36 = 0.1667 ,輸與贏的機率相同都是 15 / 36 = 0.4167 。


我們在擲骰子遊戲已經建立了模擬擲骰子的亂數表,現在我們繼續來模擬遊戲的勝負吧!


首先,我們把記錄骰子點數的陣列擴展到 1000 個元素,這也是說我們會模擬 1000 次遊戲的勝負。當然,我們需要加入
#define SIZE 1000


這樣宣告陣列就可以直接用 SIZE 代入即可,若是需要更改模擬次數,調整 SIZE 的值就可以了。


另外,我們需要加入以下三個變數的宣告
int counter1 = 0; // 累計 points1 贏的次數
int counter2 = 0; // 累計 points2 贏的次數
int counter3 = 0; // 累計平手的次數


這三個變數分別記錄陣列 points1 贏的次數,陣列 points2 贏的次數,以及平手的次數。我們假設 points1 記錄電腦 A 擲出的點數, points2 為電腦 B 擲出的點數,所有的程式碼如下
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define SIZE 1000

int main(void)
{
    int points1[SIZE]; // 第一組骰子表格
    int points2[SIZE]; // 第二組骰子表格
    int temp; // 暫存變數
    int i; // 迴圈用變數
    int counter1 = 0; // 累計 points1 贏的次數
    int counter2 = 0; // 累計 points2 贏的次數
    int counter3 = 0; // 累計平手的次數
    
    srand(time(NULL));
        
    // 建立兩組骰子的亂數表
    for (i = 0; i < SIZE; i++) {
        temp = rand() % 6;
        if (temp == 0) {
            temp = 6;
        }
        points1[i] = temp;
        
        temp = rand() % 6;
        if (temp == 0) {
            temp = 6;
        }
        points2[i] = temp;
    }
    
    // 進行兩組骰子的大小比較
    for (i = 0; i < SIZE; i++) {
        if (points1[i] == points2[i]) {
             counter3++;
        }
        
        if (points1[i] > points2[i]) {
             counter1++;
        }
        
        if (points1[i] < points2[i]) {
             counter2++;
        }
    }
    
    // 印出模擬結果
    printf("\n進行 %d 次擲骰子模擬\n", SIZE);
    printf("電腦 A 贏了 %d 次, 機率為 %f\n", counter1, (float) counter1 / SIZE);
    printf("電腦 B 贏了 %d 次, 機率為 %f\n", counter2, (float) counter2 / SIZE);
    printf("雙方平手 %d 次, 機率為 %f\n", counter3, (float) counter3 / SIZE);
    
    return 0;
}

/* 《程式語言教學誌》的範例程式
    http://pydoing.blogspot.com/
    檔名:dice5.c
    功能:簡單的擲骰子遊戲
    作者:張凱慶
    時間:西元2010年7月 */


程式主要增加了第 34 行到第 47 行
// 進行兩組骰子的大小比較
for (i = 0; i < SIZE; i++) {
    if (points1[i] == points2[i]) {
         counter3++;
    }
        
    if (points1[i] > points2[i]) {
         counter1++;
    }
        
    if (points1[i] < points2[i]) {
         counter2++;
    }
}


我們用一個 for 迴圈重新循序存取兩個陣列中儲存的點數值,再進行相等、大於或小於的測試,那一項為真,就將相關變數遞增。


第 49 行到第 53 行
// 印出模擬結果
printf("\n進行 %d 次擲骰子模擬\n", SIZE);
printf("電腦 A 贏了 %d 次, 機率為 %f\n", counter1, (float) counter1 / SIZE);
printf("電腦 B 贏了 %d 次, 機率為 %f\n", counter2, (float) counter2 / SIZE);
printf("雙方平手 %d 次, 機率為 %f\n", counter3, (float) counter3 / SIZE);


這裡除了顯示累計的次數外,也計算機率,注意機率要得到正確的結果,就需要用 cast 運算子強制轉換型態為浮點數。


好了,來編譯執行看看吧!



問題與討論
  1. 為什麼進行骰子點數大小比較時,是利用三個獨立分開的 if 陳述,而不是巢狀的 if-else 陳述?
  2. 請重複執行編譯程式,比較看看每一次的模擬結果有什麼不同?
  3. 將 SIZE 改成 10000 ,重新編譯執行的結果如何?




沒有留言: