I have this program here that simulates a Craps game and collects statistics about the games. My current design reflects several things i was trying to do.
1. Keeping the "Gameplay" and "Stat keeping" seperate.
2. Not to use global arrays.
3. I did not want to pass the "statistic arrays" around all my gameplay functions. Doing this would have also mixed "gameplay" with "stat keeping".
This assignment comes from a chapter about arrays. Since we have not yet learned about classes/structures, I should not be using them. There are alot of comments about the "statistic arrays" but i thought they were needed to explain how they are upkept and what they mean.
Code:
/*
Gerald Eckert
Craps Simulator.
Due: 3/30
Input: NONE.
Output: Statistics for 1000 games of craps.
Functionality: This program simulates 1000 games of craps
played by a single person. It gathers statistics about
the games and prints this information. Statistical functions
and gameplay functions are completly seperate. When a player
is determined to have won or lost in gameplay, all of the
gameplay information is sent to the statistic functions and
stored.
*/
#include <iostream>
#include <iomanip>
#include <cstdlib>
#include <time.h>
using namespace std;
/* Games to be played */
const int GAMES=1000;
/* Inidcates a win or lose */
const bool WIN_GAME=true;
const bool LOSE_GAME=false;
/* Gameplay Functions */
void play();
void shootersPoint(int);
int rollDice();
bool firstRollWin(int);
bool firstRollLose(int);
/* Statistical Functions */
void updateStats(int,bool);
void printStats(int[],int[],int);
double averageLength(int[],int[],int);
int sumArray(int[],int);
int main()
{
/*Initialize a a random seed. */
srand( time(NULL) );
/* Each call to play Simulates 1 game */
for(int i=0;i<GAMES;i++)
play();
return(0);
}
/*
* Play will start the game of craps by throwing
* 2 die. It determines if a player won or lost on
* the first roll or if the player must continue to roll.
*/
void play()
{
/* diceCount is the value of the throw*/
int diceCount=0;
/* rolls stores how many rolls were thrown. Throwing
* 2 dice counts as 1 role.*/
int rolls=0;
/* rolling 2 dice and getting the value */
diceCount = rollDice();
rolls++;
/* Checking for a win on the first roll */
if(firstRollWin(diceCount))
updateStats(rolls,WIN_GAME);
/* Check for a lose on the first roll */
else if(firstRollLose(diceCount))
updateStats(rolls,LOSE_GAME);
/* If a player does not win or lose on the first roll
* they continue to play in shootersPoint*/
else shootersPoint(diceCount);
}
/*
* shootersPoint continues gameplay when a player does not
* win or lose on the first roll. The integer argument is the
* dice count a.k.a shooters point.
*/
void shootersPoint(int shPoint)
{
/* Once inside shootersPoint 1 roll has already been thrown */
int rolls=1;
/* diceCount is the value of the throw */
int diceCount=0;
/* Loop continues untill a player has won/lost */
do
{
/* Rolling the dice */
diceCount = rollDice();
rolls++;
/* If a player rolls the shooters point they win. */
if(diceCount == shPoint)
updateStats(rolls,WIN_GAME);
/* If a plyer rolls a 7 they lose the game */
else if(diceCount == 7)
updateStats(rolls,LOSE_GAME);
/* Continue untill the player rolls a 7 or the ShootersPoint */
}while(diceCount !=7 && diceCount !=shPoint);
}
/*
* rollDice simulates the rolling of 2 die.
* It will return the sum of the dice.
*/
int rollDice()
{
int rollSum=0;
/* Generating 2 random numbers from 1 to 6 and adding their total */
rollSum = rand()%6 +1;
rollSum += rand()%6 +1;
return(rollSum);
}
/*
* This function determines whether a FIRST roll was a win.
* Returns true if the player has won.
* Returns false if the player did not win.
* int firstRoll is the sum of the 2 die.
*/
bool firstRollWin(int firstRoll)
{
/* 7 or 11 on the first Roll is a win */
if(firstRoll == 7 || firstRoll == 11)
return(true);
return(false);
}
/*
* This function determines whether a FIRST roll was a loss.
* Returns true if player lost.
* Returns false if player did not lose.
* int firstRoll is the sum of the 2 die.
*/
bool firstRollLose(int firstRoll)
{
/* 2,3,12 on the first Roll is a loss */
if(firstRoll == 2 || firstRoll == 3 || firstRoll == 12)
return(true);
return(false);
}
/********************************************************************************
************************** Statistical Functions ****************************
********************************************************************************/
/*
* updateStats will modify 2 Static arrays to keep data.
* These two arrays store how many games were won/lost and on what
* roll they were won/lost.
* EXAMPLE FOR : winning array.
* Index 1 might hold 5. This would mean 5 games were won on the 1st roll.
* Index 20 might hold 2. This would mean 2 games were won on the 20th roll.
* Index 0 will hold games that were won using more than 20 rolls.
*
* Perameters: int rolls : indicates how many rolls it took to finish the game.
* bool status : indicates a win or lose. true=win ; false=lose;
*/
void updateStats(int rolls, bool status)
{
/* counter will store how many times
* this function is accessed. Which also
* indicates how many games have been completed.*/
static int counter=0;
/* Arrays to hold win/loss/roll data.*/
static int gamesWon[21];
static int gamesLost[21];
static const int SIZE= 21;
/* Incrementing the counter */
counter++;
/* Checking if it took more than 20 rolls to win/lose.
* These wins/losses are stored in Index 0 of the respective arrays.*/
if(rolls > 20)
rolls=0;
/* If the Game was a win we update the gamesWon array.
* We increment the "roll" index which indicates that
* another game has been won with that many rolls.*/
if(status)
gamesWon[rolls]++;
/* If the Game was a lose update the gamesLost array.
* Uses the same approach as above.*/
else
gamesLost[rolls]++;
/* Checking whether all the games have been simulated.
* If they have all been simulated we will call the print.
* function to display results. */
if(counter == GAMES)
printStats(gamesWon,gamesLost,SIZE);
}
/*
* This function will add up all the elements of an
* integer array. Accepts an array and its size.
*/
int sumArray(int ar[],int size)
{
int sum=0;
for(int i=0;i<size;i++)
sum += ar[i];
return(sum);
}
/*
* averageLength will compute the average length of a game
* based on rolls. Excluding games that took longer than
* 20 rolls. The two arrays being passed in contain the
* total wins according to roll #.
* EXAMPLE.
* Index 3 of the wins[] might contain 15.
* This would indicate 15 games were won after 3 rolls
* Resulting in (3 rolls * 15 games) = 45 rolls.
*
* Using this logic we can calculate the total rolls for each
* array and determine an average game length.
*/
double averageLength(int wins[], int losses[],int size)
{
int totalRolls=0;
double average=0;
/* Calculating the total rolls
* Index 0 is not used*/
for(int i=1;i<size;i++)
{
totalRolls += ( wins[i] * i );
totalRolls += ( losses[i] * i);
}
average= static_cast<double>(totalRolls) / GAMES ;
return( average );
}
/*
* printStats will calculate some final statistics
* and then print all of the statistics. This funciton
* accepts the 2 integer arrays holding the statistical
* information and an integer indicating their size.
*/
void printStats(int wins[], int losses[],int size)
{
/* Calling sumArray to add up all of the win/losses
* for each statstic array.*/
int totalWins= sumArray(wins,size);
int totalLosses= sumArray(losses,size);
/* Calculating a win percentage (winning games / total games) */
double winPercentage= ( static_cast<double>(totalWins) / GAMES )*100;
/* Calling averageLength with the 2 statistic arrays to calculate
* the average length of the games.*/
double averageGameLength= averageLength(wins,losses,size);
/* Printing the simulation Results */
cout<<"************ CRAPS SIMULATOR *************"<<endl;
cout<<"Total Games Played : "<<GAMES<<endl;
cout<<"Total Games Won : "<<totalWins<<endl;
cout<<"Total Games Lost : "<<totalLosses<<endl;
cout<<setprecision(3)<<fixed<<endl;
cout<<"Win Percentage : "<<winPercentage<<" % "<<endl;
cout<<"Average Game Length : "<<averageGameLength<<" rolls *"<<endl;
cout<<"__________________________________________"<<endl;
cout<<endl;
cout<<"Games won per Roll (Roll Count : Games Won) "<<endl;
cout<<endl;
for(int i=1;i<21;i++)
cout<<"Roll "<<i<<": "<<wins[i]<<endl;
cout<<"More than 20 rolls : "<<wins[0]<<endl;
cout<<"___________________________________________"<<endl;
cout<<endl;
cout<<"Games lost per Roll (Roll Count : Games Lost)"<<endl;
cout<<endl;
for(int i=1;i<21;i++)
cout<<"Roll "<<i<<": "<<losses[i]<<endl;
cout<<"More than 20 rolls : "<<losses[0]<<endl;
cout<<"_____________________________________________________"<<endl;
cout<<"* : Games that took more than 20 rolls to finish were"<<endl;
cout<<" not included in the \"Average Game\" calculations"<<endl;
}
I just wanted comments on the design of the simulation. It works good and does what i want it to.
Well, im not trying to make a game of craps for other people to play nor am i trying to test how well my craps game works. It is a simple simulation of a craps game that keeps statistics on rolls / wins / losses. I guess i should narrow down my question. Comments on how i am implementing the "stat keeping" and "the gameplay" rather than overall design.
AFAIK, game developer often write them in low level operation such as using hexadecmal value and bitwise operation.
Thatīs true for high speed 3D engines maybe, but I really doubt any serious software developer will prefer cryptic code to regular operations when speed doesnīt matter at all.
Bookmarks