C Primer Plus 第12章 12.5 擲骰子

擲骰子最廣泛的形式是用兩個6面骰子。ide

計算機能夠設計一種具備任意麪數的骰子,先從6面開始,再進行擴展。函數

咱們想獲得從1到6之間的一個隨機數。然而,rand()產生的是從0到RAND_MAX範圍內的整數;RAND_MAX在stdlib.h中定義,它一般是INT_MAX。所以,須要作一些調整。下面是一種方法:設計

一、把隨機數對6取模,將產生從0到5的整數。code

二、加1.新數將爲從1到6範圍內的整數。原型

三、爲了方便擴展,將步驟1中的數字6用骰子面數來代替。編譯器

下面的代碼實現了這些想法:io

#include <stdlib.h>        /*爲rand()函數提供原型*/
int rollem(int sides)
{
    int roll;
    
    roll = rand()%sides + 1;
    return roll;
}

進一步,咱們想實現這樣的功能:它容許擲任意個骰子,而且返回點數總和。程序清單12.11實現了這樣的功能。編譯

/*diceroll.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()的調用次數。例子自己有一點不妥,但它顯示了外部變量的如何工做的。ast

再次,文件包含下面的語句:function

#include "diceroll.h"

若是使用諸如rand()的標準庫函數,您須要在程序中包含標準頭文件(對rand()來講是stdlib.h),而不是聲明函數,由於頭文件中已經包含了正確的聲明。咱們將效仿這一作法,提供一個頭文件diceroll.h以供函數roll_n_dice()使用。將文件名置於雙引號而非尖括號中, 是爲了指示編譯器在本地尋找文件,而不是到編譯器存放標準頭文件的標準位置去尋找文件。「在本地尋找」的意義取決於具體的C實現。一些常看法釋是將頭文件與源代碼文件放在同一個目錄或文件夾中。程序清單12.12顯示了該頭文件的內容。

程序清單12.12 diceroll.h文件

//diceroll.h

extern int roll_count;

int roll_n_dice(int dice,int sides);

這個頭文件中包含函數原型聲明一和個extern聲明。由於文件diceroll.c包含了這一頭文件,它也就實際上包含了roll_count的兩個聲明:

extern int roll_count;    //來自頭文件

int roll_count = 0;       //來自源代碼文件

這是能夠的,一個變量只能夠有一個定義聲明,但使用extern的聲明是一個引用聲明,這樣的聲明想用多少就能夠用多少。

使用roll_n_dice()的程序也應該包含這一頭文件。這樣作不單單提供roll_n_dice()原型,還使得roll_count對程序可用。程序清單12.13證實了這些。

//manydice.c  --屢次擲骰子的模擬程序
//與diceroll.c一塊兒編譯
#include<stdio.h>
#include<stdlib.h>        //爲srand()提供原型
#include<time.h>          //爲time()提供原型
#include"dicerlll.h"      //爲roll_n_dice()和roll-count提供原型

int main(void)
{
    int dice ,roll;
    int sides;

    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");
        scanf("%d",&dice);
        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);    /*使用外部變量*/
    printf("Good Fortune To You!\n");
    return 0;
}

將程序清單12.13與包含程序清單12.11的文件一塊兒編譯。爲了簡化問題,把程序清單12.十一、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 dece.
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
You have rolled a 5 using 2 6-sided dice.
How many sides?Enter 0 to stop.
0
The rollem() funcation was called 6 times.
GOOD FORRUNE TO YOU!

由於程序使用srand()來隨機肯定隨機數種子,因此大多數狀況下,即便有相同的輸入也不可能獲得相同的輸出。注意,manydice.c中的main()確實能夠訪問diceroll.c中定義的變量roll_count。

能夠使用多種方式使用roll_n_dice()。對於sides爲2的情形,程序模仿擲硬幣,面朝上爲2,背朝上爲1.您能夠很容易地修改程序來像顯示整體結果那樣顯示個別結果,或者建一個擲雙骰子賭博模擬器。

相關文章
相關標籤/搜索