3.9 案例:机会游戏与 enum 简介
一个最常见的机会游戏是投骰子游戏,游戏规则如下:
游戏者投两枚骰子,每个骰于有六面,这些面包含1、2、3、4、5、6个点。投两枚骰于之后,计算点数之和。如果第一次投时的和为7或11,则游戏者获胜。如果第一次投时的和2、3或12,则游戏者输,庄家赢。如果第一次投时的和为4、5、6、8、9或10,则这个和成为游戏者的点数。
要想赢,就要继续投骰子,直到赚到点数。如果投七次之后还没有赚到点数,则游戏者输。
图3.10中的程序模拟了投骰子游戏,图3.11 显示了几个示例的执行结果。
1 // Fig. 3.10: figO3_lO.cpp // Craps #include <iostream.h> #include <stdlib.h> #include <time.h> int rollDice( void ); // function prototype int main (){ enum status{CONTINUE,WON,LOST}; int sum, myPoint; status gameStatus; srand( time( NULL ) ); sum = rollDice( ); // first roll of the dice switch ( sum ) { case 1: case 11: // win on first roll gameStatus = WON; break; case 2: case 3: case 12: // lose on first roll gameStatus = LOST; break; default: // remember point gameStatus = CONTINUE; myPoint = sum; cout << "point is "<< myPoint << endl; break; // optional while { gameStatus == CONTINUE ) { // keep rolling sum = rollDice( ); if ( sum = myPoknt ) // win by making point gameStatus = wON; else if ( sum == 7 ) // lose by rolling 7 gameStatus = LOST; } if ( gameStatus == WON ) cout << "Player wins" << end1; else cout << "Player loses" << endl; return 0; } int rollDice( void ){ int diel, die2, workSum; die1 = 1 + rand( ) % 6; die2 = 1 + rand( ) % 6; workSum = diel + die2; cout << "Player rolled" << diel <<" + "<< die2 << " = " << workSum << endl; return workSum; } }
图 3.10 模拟投骰子游戏的程序
Player rolled 6 + 5 = 11 Player wins Player rolled 6 + 6 = 12 Player loses Player rolled 4 + 6 = 10 Point is 10 Player rolled 2 + 4 = 6 Player rolled 6 + 5 11 Player rolled 3 + 3 = 6 Player rolled 6 + 4 10 Player wins Player rolled 1 + 3 = 4 Point is q Player rolled 1 + 4 = 5 Player rolled 5 + 4 9 Player rolled 4 + 6 - 10 Player rolled 6 + 3 - 9 Player rolled 1 + 2 = 3 Player rolled 5 + 2 = 7 Player loses
图 3.11 投骰子游戏程序示例的执行结果
注意,游戏者首先要投两枚骰子,后面也是。我们定义rollDice函数投骰子、计算并打印点数和。函数rollDice定义一次,但可从程序的两个地方调用。有趣的是,rollDice不取参数,因此在参数表中用void表示。函数rollDice返回投两枚骰子的点数和,因此在函数首部定义的返回类型为int。
这个游戏相当复杂。游戏者第一次投两枚骰子时可能输也可能赢,也可能投好几次才会定出输赢。变量gameStatus跟踪这个状态,将其声明为Status类型。下列语句:
enum Status{ CONTIEUE,WON,LOST);
生成用户自定义类型(user-defined type)即枚举类型(enume ration)枚举类型由关键字enum和类型名(这里是Status)构成,是—组用标识符表示的整数常量。这些枚举常量(enume ration constant)的值从0开始,增量为1,但也可以指定其他的增量值。在上述枚举中,CONTINUE指定为数值0,WON指定为数值1,LOST指定为数值2。enum中的标识符必须惟一,但不同枚举常量可以取相同的值。
编程技巧3.7
作为用户自定义类型名的标识符,其第一个字母应大写。
用户自定义类型Status的变量只能赋给枚举中声明的三个值之一。游戏获胜时,gameStatus设置为WON;游戏失败时,gameStatus设置为LOST;否则gameStatus设置为CONTINUE.可以再次投骰子。
常见编程错误3.17
对枚举类型变量指定等价于枚常量的整数值是个语法错误。
另—个常用枚举是:
enum Months { JAN = 1,FEB,MAR,APR, MAY,JUN, JUL,AUG,SEP,OCT,NOV,DEC};
生成用户自定义类型Months,用枚举常量表示一年的月份。由于上述枚举中第一个值显式指定为1,因此其余值每次递增1,取值为1到12。任何枚举常量可以在枚举定义中指定一个整数值,后面的值用1递增。
常见编程错误3.18
定义枚举常量之后,想对枚举常量指定另一个值是个语法错误。
编程技巧3.8
枚举常量名用大写字母能使枚举常量在程序中更醒目,使程序更注意到枚举常量不是变量。
编程技巧3.9
用枚举而不用整数常量能使程序更清晰。
第一次投骰子之后,如果游戏获胜,则跳过while结构体,因为gameStatus不等于CONTINUE。
程序进入if/else结构,在gameStatus等于WON时打印“Playerwins",在gameStatus等于LOST时打印“Playerloses"。
第一次投骰子之后,如果游戏没有结束,则sum保存在myPoint中,由于gameStatus等于CONTINUE,因此执行while结构中的程序。每次执行while结构中的程序时,调用rollDice产生新的sum。如果sum符合myPoint,则gameStatus设置为WON,while测试失败,if/else结构打印“Playerwins”,终止执行。如果sum等于7,则gameStatus设置为LOST,while测试失败,if/el~结构打印“Playerloses”,终止执行。
注意其中使用了前面介绍的各种程序控制机制。投骰子程序使用两个函数main和rollDice,并使用switch、while、if/else和嵌套if结构。练习中,我们要介绍投骰子程序的各种有趣的特点。