C/C++實現投骰子游戲
我們將要模擬一個非常流行的遊戲——擲骰子。
骰子的形式多種多樣, 最普遍的是使用兩個6面骰子。在一些冒險遊戲中,會使用5種骰子:4面、6 面、8面、12面和20面。聰明的古希臘人證明了只有5種正多面體,它們的所 有面都具有相同的形狀和大小。各種不同型別的骰子就是根據這些正多面體 發展而來。也可以做成其他面數的,但是其所有的面不會都相等,因此各個 面朝上的機率就不同。
計算機計算不用考慮幾何的限制,所以可以設計任意麵數的電子骰子。 我們先從6面開始。
我們想獲得1~6的隨機數。然而,rand()生成的隨機數在0~ RAND_MAX之間。RAND_MAX被定義在stdlib.h中,其值通常是 INT_MAX。因此,需要進行一些調整,方法如下。
1.把隨機數求模6,獲得的整數在0~5之間。
2.結果加1,新值在1~6之間。
3.為方便以後擴充套件,把第1步中的數字6替換成骰子面數。
下面的程式碼實現了這3個步驟:
#include <stdlib.h> /* 提供rand()的原型 */ int rollem(int sides) { int roll; roll = rand() % sides + 1; return roll; }
我們還想用一個函式提示使用者選擇任意麵數的骰子,並返回點數總和。
/* diceroll.c -- 擲骰子模擬程式 */ /* 與 mandydice.c 一起編譯 */ #include "diceroll.h" #include <stdio.h> #include <stdlib.h> /* 提供庫函式 rand()的原型 */ int roll_count = 0; /* 外部連結 */ static int rollem(int sides) /* 該函式屬於該檔案私有 */ { int roll; roll = rand() % sides + 1; ++roll_count; /* 計算函式呼叫次數 */ return roll; } int roll_n_dice(int dice, int sides) { int d; int total = 0; if (sides < 2) { printf("Need at least 2 sides.\n"); return -2; } if (dice < 1) { printf("Need at least 1 die.\n"); return -1; } for (d = 0; d < dice; d++) total += rollem(sides); return total; }
該檔案加入了新元素。第一,rollem()函式屬於該檔案私有,它是 roll_n_dice()的輔助函式。第二,為了演示外部連結的特性,該檔案聲明瞭 一個外部變數roll_count。該變數統計呼叫rollem()函式的次數。這樣設計有 點蹩腳,僅為了演示外部變數的特性。第三,該檔案包含以下預處理指令:
#include "diceroll.h"
如果使用標準庫函式,如 rand(),要在當前檔案中包含標準標頭檔案(對 rand()而言要包含stdlib.h),而不是宣告該函式。因為標頭檔案中已經包含了 正確的函式原型。我們效仿這一做法,把roll_n_dice()函式的原型放在 diceroll.h標頭檔案中。把檔名放在雙引號中而不是尖括號中,指示編譯器在 本地查詢檔案,而不是到編譯器存放標準標頭檔案的位置去查詢檔案。“本地 查詢”的含義取決於具體的實現。一些常見的實現把標頭檔案與原始碼檔案或 工程檔案(如果編譯器使用它們的話)放在相同的目錄或資料夾中。
//diceroll.h extern int roll_count; int roll_n_dice(int dice,int sides);
該標頭檔案中包含一個函式原型和一個 extern 宣告。由於 direroll.c 檔案 包含了該檔案, direroll.c實際上包含了roll_count的兩個宣告:
extern int roll_count; // 標頭檔案中的宣告(引用式宣告) int roll_count = 0; // 原始碼檔案中的宣告(定義式宣告)
這樣做沒問題。一個變數只能有一個定義式宣告,但是帶 extern 的宣告 是引用式宣告,可以有多個引用式宣告。
使用 roll_n_dice()函式的程式都要包含 diceroll.c 標頭檔案。包含該標頭檔案 後,程式便可使用roll_n_dice()函式和roll_count變數。
/* manydice.c -- 多次擲骰子的模擬程式 */ /* 與 diceroll.c 一起編譯*/ #include <stdio.h> #include <stdlib.h> /* 為庫函式 srand() 提供原型 */ #include <time.h> /* 為 time() 提供原型 */ #include "diceroll.h" /* 為roll_n_dice()提供原型,為roll_count變數 提供宣告 */ int main(void) { int dice, roll; int sides; int status; srand((unsigned int) time(0)); /* 隨機種子 */ printf("Enter the number of sides per die, 0 to stop.\n"); while (scanf("%d", &sides) == 1 && sides > 0) { printf("How many dice?\n"); if ((status = scanf("%d", &dice)) != 1) { 905 if (status == EOF) break; /* 退出迴圈 */ else { printf("You should have entered an integer."); printf(" Let's begin again.\n"); while (getchar() != '\n') continue; /* 處理錯誤的輸入 */ printf("How many sides? Enter 0 to stop.\n"); continue; /* 進入迴圈的下一輪迭代 */ } } roll = roll_n_dice(dice, sides); printf("You have rolled a %d using %d %d-sided dice.\n",roll, dice, sides); printf("How many sides? Enter 0 to stop.\n"); } printf("The rollem() function was called %d times.\n",roll_count); /* 使用外部變數 */ 906 printf("GOOD FORTUNE TO YOU!\n"); return 0; }
要與包含程式清單12.11的檔案一起編譯該檔案。可以把程式清單 12.11、12.12和12.13都放在同一資料夾或目錄中。執行該程式,下面是一個 輸出示例:
Enter the number of sides per die, 0 to stop. 6 How many dice? 2 You have rolled a 12 using 2 6-sided dice. How many sides? Enter 0 to stop. 6 How many dice? 2 You have rolled a 4 using 2 6-sided dice. How many sides? Enter 0 to stop. 6 How many dice? 2 907 You have rolled a 5 using 2 6-sided dice. How many sides? Enter 0 to stop. 0 The rollem() function was called 6 times. GOOD FORTUNE TO YOU!
因為該程式使用了srand()隨機生成隨機數種子,所以大多數情況下,即 使輸入相同也很難得到相同的輸出。注意,manydice.c中的main()訪問了定 義在diceroll.c中的roll_count變數。
有3種情況可以導致外層while迴圈結束:side小於1、輸入型別不匹配 (此時scanf()返回0)、遇到檔案結尾(返回值是EOF)。為了讀取骰子的 點數,該程式處理檔案結尾的方式(退出while迴圈)與處理型別不匹配 (進入迴圈的下一輪迭代)的情況不同。
可以通過多種方式使用roll_n_dice()。sides等於2時,程式模仿擲硬 幣,“正面朝上”為2,“反面朝上”為1(或者反過來表示也行)。很容易修改 該程式單獨顯示點數的結果,或者構建一個骰子模擬器。如果要擲多次骰子 (如在一些角色扮演類遊戲中),可以很容易地修改程式以輸出類似的結 果:
Enter the number of sets; enter q to stop. 18 How many sides and how many dice? 6 3 Here are 18 sets of 3 6-sided throws. 908 12 10 6 9 8 14 8 15 9 14 12 17 11 7 10 13 8 14 How many sets? Enter q to stop. q
rand1()或 rand()(不是 rollem())還可以用來建立一個猜數字程式,讓 計算機選定一個數字,你來猜。讀者感興趣的話可以自己編寫這個程式。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。