基于C++实现掷双骰游戏的示例代码
在最流行的博彩游戏中有一种名为“掷双骰”(craps)的骰子游戏,这种游戏在世界各地的娱乐场所和大街小巷非常受欢迎。游戏的规则很简单:
玩家掷两个骰子。每个骰子有六面,分别含有1、2、3、4、5和6个点。掷完骰子后,计算两个朝上的面的点数之和。
1、如果首次投掷的点数总和是7或者11,那么玩家赢;
2、如果首次投掷的点数只和事2、3或者12(称为"craps"),那么玩家输(即庄家赢);
3、如果首次投掷的点数只和事4、5、6、7、8、9或者10,那么这个和就成为玩家的“目标点数”。要想赢的话,玩家必须连续的掷骰子直到点数与这个目标点数相同为止,即“得到了点数”。但在得到点数前,如果掷到的是7,就会输掉。
#include <iostream> #include <cstdlib> #include <ctime> using namespace std; unsigned int rollDice(); int main() { enum Status {CONTINUE, WON, LOST}; //这个就是自定义一个变量类型,就类似于int,double这种,即这里的说白了就是设置一个枚举类变量类 //而这个类的关键字就是Status,以这个类型定义的变量只能取枚举内的几个值,而这几个值又对应了数字。 srand(static_cast<unsigned int>(time(0))); unsigned int myPoint = 0; Status gameStatus = CONTINUE; unsigned int sumOfDice = rollDice(); switch (sumOfDice) { case 7: case 11: gameStatus = WON; break; case 2: case 3: case 12: gameStatus = LOST; break; default: gameStatus = CONTINUE; myPoint = sumOfDice; cout << "Point is " << myPoint << endl; break; }; while (gameStatus == CONTINUE){ sumOfDice = rollDice(); if (sumOfDice == myPoint) gameStatus = WON; else if (sumOfDice == 7) gameStatus = LOST; } if (gameStatus == WON) cout << "Player wins" << endl; else cout << "Player lose" << endl; } unsigned int rollDice(){ unsigned int die1 = 1 + rand() % 6; unsigned int die2 = 1 + rand() % 6; unsigned int sum = die1 + die2; cout << "Player rolled: " << die1 << " + " << die2 << " = " << sum << endl; return sum; }
这个是我拿来当作笔记的,主要是为了记住这么个问题,当我要想循环的实现博彩游戏并且统计输赢的时候,会自然而然的想到在外部套一个for循环去执行,但是这样就会涉及到一个问题,即随机数的生成,按照我最开始的理解是随着循环的进行,给srand提供的seed不同(也就是实参time(0))就会在每次循环都产生不同的随机序列。即代码如下
#include <iostream> #include <cstdlib> #include <ctime> using namespace std; unsigned int rollDice(); int main() { int winNum = 0; int loseNum = 0; enum Status {CONTINUE, WON, LOST}; //这个就是自定义一个变量类型,就类似于int,double这种,即这里的说白了就是设置一个枚举类变量类 //而这个类的关键字就是Status,以这个类型定义的变量只能取枚举内的几个值,而这几个值又对应了数字。 for (int i = 0; i < 100000; ++i) { srand(static_cast<unsigned int>(time(0))); unsigned int myPoint = 0; Status gameStatus = CONTINUE; unsigned int sumOfDice = rollDice(); switch (sumOfDice) { case 7: case 11: gameStatus = WON; break; case 2: case 3: case 12: gameStatus = LOST; break; default: gameStatus = CONTINUE; myPoint = sumOfDice; // cout << "Point is " << myPoint << endl; break; }; while (gameStatus == CONTINUE) { sumOfDice = rollDice(); if (sumOfDice == myPoint) gameStatus = WON; else if (sumOfDice == 7) gameStatus = LOST; } if (gameStatus == WON) { // cout << "Player wins" << endl; winNum++; } else { // cout << "Player lose" << endl; loseNum++; } } cout << "WIN: " << winNum << endl; cout << "LOSE: " << loseNum << endl; } unsigned int rollDice(){ unsigned int die1 = 1 + rand() % 6; unsigned int die2 = 1 + rand() % 6; unsigned int sum = die1 + die2; // cout << "Player rolled: " << die1 << " + " << die2 // << " = " << sum << endl; return sum; }
然而统计运行结果是:
WIN: 0
LOSE: 100000
也就是说一旦第一次是输了,那么就一直都是输的,为什么?
原因在于程序运行太快,而time(0)提供的时间戳是以秒为单位提供的,而程序1s内就执行完了,自然就提供的seed是一样的,那么rand的序列也是一样,所以就一直是赢或者输,那么我要是非要它不一直赢或者输了?可以这样,将循环次数设置得更大,让程序1s内运行不完,不就可以提供不同的时间戳了?而事实是这样也是可行的,如图,是我设置1000w次循环的统计结果。
WIN: 8703168
LOSE: 1296832
当然,治标不治本,这还是没有达到每次循环都是无预测性的随机数,目前还要学习其他东西,等我有时间了再来思考这个问题~