Dice Code
Header File
#ifndef _DnD_Dice_Set__
#define _DnD_Dice_Set__
enum diceFlag{D_4, D_6, D_8, D_10, D_12, D_20, D_100, GENERIC}; //Flag the type of dice object created
//within the object constructor
const int d4 = 4; //Defines the size of a d4 die
const int d6 = 6; //Defines the size of a d6 die
const int d8 = 8; //Defines the size of a d8 die
const int d10 = 10; //Defines the size of a d10 die
const int d12 = 12; //Defines the size of a d12 die
const int d20 = 20; //Defines the size of a d20 die
const int d100 = 100; //Defines the size of a d100 die
const double EPSILON = 0.00000001;
class RollTally
{
public:
~RollTally();
RollTally();
private:
unsigned int m_d4_counter[d4];
unsigned int m_d6_counter[d6];
unsigned int m_d8_counter[d8];
unsigned int m_d10_counter[d10];
unsigned int m_d12_counter[d12];
unsigned int m_d20_counter[d20];
unsigned int m_d100_counter[d100];
friend class Dice;
};
// This base class implements a simulation of a generic, n-sided die
class Dice
{
public:
//Constructors
~Dice();
Dice();
//Manipulators
void reset(); // re-write this function, it no longer has adequate functionality
virtual void roll(unsigned int);
void setNumberOfSides(unsigned int);
//Accessors
int getSide() const;
int getRolls() const;
double getAverage() const;
double ratio() const;
diceFlag thisIs() const;
//Binary Operators(relational and arithmetic)
bool operator < (Dice) const;
bool operator > (Dice) const;
bool operator >= (Dice) const;
bool operator <= (Dice) const;
bool operator == (Dice) const;
bool operator != (Dice) const;
//Assignment Operator
const Dice& Dice::operator = (const Dice&); // only works for dice flaged as the same type
protected:
diceFlag thisDieIsA;
//
unsigned int m_num_sides; // remember to set this withing derived classes
unsigned int m_side;
double m_average; // needs math to get an average
unsigned int m_rolls;
static unsigned int m_totalRolls; // needs accessor
static RollTally m_side_counter; // needs accessor
//Internal Member Functions
void generateRandomSeed();
void f_roll(unsigned int); // roll the dice and increment counters
//Friends of this class so they can use the overloaded operators
friend class D4;
friend class D6;
friend class D8;
friend class D10;
friend class D12;
friend class D20;
friend class D100;
};
//Derived classes
class D4 : public Dice
{
public:
~D4(); //destructor
D4(); //default constructor
void roll();
private:
static int m_number_of_sides;
};
class D6 : public Dice
{
public:
~D6(); //destructor
D6(); //default constructor
void roll();
private:
static int m_number_of_sides;
};
class D8 : public Dice
{
public:
~D8(); //destructor
D8(); //default constructor
void roll();
private:
static int m_number_of_sides;
};
class D10 : public Dice
{
public:
~D10(); //destructor
D10(); //default constructor
void roll();
private:
static int m_number_of_sides;
};
class D12 : public Dice
{
public:
~D12(); //destructor
D12(); //default constructor
void roll();
private:
static int m_number_of_sides;
};
class D20 : public Dice
{
public:
~D20(); //destructor
D20(); //default constructor
void roll();
private:
static int m_number_of_sides;
};
class D100 : public Dice
{
public:
~D100(); //destructor
D100(); //default constructor
void roll();
private:
static int m_number_of_sides;
};
#endif
Implementation File
#include "iostream.h"
#include "cstdlib.h" // srand, rand functions
#include "ctime.h" // time_t struct, time function
#include "cmath.h"
#include "Dice.h"
using namespace std;
//Static Data Initialization ***************************
unsigned int Dice::m_totalRolls = 0;
RollTally Dice::m_side_counter;
int D4::m_number_of_sides = d4;
int D6::m_number_of_sides = d6;
int D8::m_number_of_sides = d8;
int D10::m_number_of_sides = d10;
int D12::m_number_of_sides = d12;
int D20::m_number_of_sides = d20;
int D100::m_number_of_sides = d100;
//Destructors ****************************************
**************************
RollTally::~RollTally(){}
Dice::~Dice(){}
D4::~D4(){}
D6::~D6(){}
D8::~D8(){}
D10::~D10(){}
D12::~D12(){}
D20::~D20(){}
D100::~D100(){}
//Constructors ****************************************
*************************
//Initialization Constructor for private data member of the Dice class
RollTally::RollTally()
{
int counter = d100; // this is the size of the largest array declared in the
// class this class contains as a data mamber
for(int i = 0; i < counter; i++) // initializes the counter array
{
if(i < d4)
{
m_d4_counter[i] = 0;
}
if(i < d6)
{
m_d6_counter[i] = 0;
}
if(i < d8)
{
m_d8_counter[i] = 0;
}
if(i < d10)
{
m_d10_counter[i] = 0;
}
if(i < d12)
{
m_d12_counter[i] = 0;
}
if(i < d20)
{
m_d20_counter[i] = 0;
}
m_d100_counter[i] = 0;
}
}
// This Die is created with a default side of 6. to use this object with
//a different number of sides, use the Dice(int #sides) constructor
Dice::Dice()
{
thisDieIsA = GENERIC;
m_num_sides = d6;
if(m_totalRolls == 0)
{
generateRandomSeed();
}
reset();
f_roll(d6);// default dice side
}
D4::D4()
{
thisDieIsA = D_4;
m_num_sides = m_number_of_sides;
if(m_totalRolls == 0)
{
generateRandomSeed();
}
reset();
f_roll(m_number_of_sides);
}
D6::D6()
{
thisDieIsA = D_6;
m_num_sides = m_number_of_sides;
if(m_totalRolls == 0)
{
generateRandomSeed();
}
reset();
f_roll(m_number_of_sides);
}
D8::D8()
{
thisDieIsA = D_8;
m_num_sides = m_number_of_sides;
if(m_totalRolls == 0)
{
generateRandomSeed();
}
reset();
f_roll(m_number_of_sides);
}
D10::D10()
{
thisDieIsA = D_10;
m_num_sides = m_number_of_sides;
if(m_totalRolls == 0)
{
generateRandomSeed();
}
reset();
f_roll(m_number_of_sides);
}
D12::D12()
{
thisDieIsA = D_12;
m_num_sides = m_number_of_sides;
if(m_totalRolls == 0)
{
generateRandomSeed();
}
reset();
f_roll(m_number_of_sides);
}
D20::D20()
{
thisDieIsA = D_20;
m_num_sides = m_number_of_sides;
if(m_totalRolls == 0)
{
generateRandomSeed();
}
reset();
f_roll(m_number_of_sides);
}
D100::D100()
{
thisDieIsA = D_100;
m_num_sides = m_number_of_sides;
if(m_totalRolls == 0)
{
generateRandomSeed();
}
reset();
f_roll(m_number_of_sides);
}
//Modifiers ****************************************
*******************************
void Dice::generateRandomSeed()
{
//Generate new random seed
time_t seconds;
time(&seconds); // store current time (in secs) into address-of seconds
srand((unsigned int) seconds); // sets the random generator’s seed to ‘seconds’
}
void Dice::f_roll(unsigned int numberOfSides)
{
int randomNum = rand(); // returns a value between 0 .. RAND_MAX
m_rolls++; //increment counter for THIS object
m_totalRolls++; //increment counter for total rolls (static member of class)
int rollHolder;
rollHolder = randomNum % numberOfSides; // placeholder so the counter arrays
// can increment the proper element
//(element corresponds to a number between
//0 and numberOfSides
m_side = rollHolder +1;
if(thisDieIsA != GENERIC) //ONLY INCREMENT THESE COUNTERS FOR THE DERIVED CLASSES
{
switch(numberOfSides)
{
case d4: m_side_counter.m_d4_counter[rollHolder]+
+; break;
case d6: m_side_counter.m_d6_counter[rollHolder]+
+; break;
case d8: m_side_counter.m_d8_counter[rollHolder]+
+; break;
case d10: m_side_counter.m_d10_counter[rollHolder]
++; break;
case d12: m_side_counter.m_d12_counter[rollHolder]
++; break;
case d20: m_side_counter.m_d20_counter[rollHolder]
++; break;
case d100: m_side_counter.m_d100_counter[rollHolder]
++; break;
}
}
//Calculate new average every time die is rolled
if(m_rolls > 1)
m_average = (m_average + static_cast
(m_side)) / 2;
else
m_average = m_side;
}
void Dice::roll(unsigned int num_sides)
{
f_roll(num_sides);
}
void D4::roll()
{
f_roll(m_number_of_sides);
}
void D6::roll()
{
f_roll(m_number_of_sides);
}
void D8::roll()
{
f_roll(m_number_of_sides);
}
void D10::roll()
{
f_roll(m_number_of_sides);
}
void D12::roll()
{
f_roll(m_number_of_sides);
}
void D20::roll()
{
f_roll(m_number_of_sides);
}
void D100::roll()
{
f_roll(m_number_of_sides);
}
void Dice::reset()
{
m_average = 0.0;
m_rolls = 0;
}
void Dice::setNumberOfSides(unsigned int num_sides)
{
int error = 0;
try
{
if(thisDieIsA != GENERIC)
{
throw error;
}
m_num_sides = num_sides;
}
catch(...)
{
cout << "Attempting to change the type of this Die is prohibited." << endl;
cout << "If you need to change the type of this Die, declare your" << endl;
cout << "die as a generic Dice type, and not D4, D6, etc." << endl << endl;
}
}
//Accessors*************************************************************************
int Dice::getSide() const
{
return m_side;
}
int Dice::getRolls() const
{
return m_rolls;
}
double Dice::getAverage() const
{
return m_average;
}
double Dice::ratio() const
{
double ratio = (static_cast(m_side) / static_cast(m_num_sides));
return ratio;
}
diceFlag Dice::thisIs() const
{
return thisDieIsA;
}
//Operators ************************************************************************
bool Dice::operator<(Dice rhs) const
{
Dice thisDie;
thisDie = *this;
if(thisDie.ratio() < rhs.ratio())
return true;
else
return false;
}
bool Dice::operator>(Dice rhs) const
{
Dice thisDie;
thisDie = *this;
if(thisDie.ratio() > rhs.ratio())
return true;
else
return false;
}
bool Dice::operator >= (Dice rhs) const
{
Dice thisDie;
thisDie = *this;
if(thisDie.ratio() >= rhs.ratio())
return true;
else
return false;
}
bool Dice::operator <= (Dice rhs) const
{
Dice thisDie;
thisDie = *this;
if(thisDie.ratio() <= rhs.ratio())
return true;
else
return false;
}
bool Dice::operator == (Dice rhs) const
{
Dice thisDie;
thisDie = *this;
if(fabs(thisDie.ratio() - rhs.ratio()) < EPSILON)
return true;
else
return false;
}
bool Dice::operator != (Dice rhs) const
{
Dice thisDie;
thisDie = *this;
if(thisDie == rhs)
return false;
else
return false;
}
const Dice& Dice::operator = (const Dice& rhs)
{
int error = 0;
try
{
if((this->thisIs() != rhs.thisIs()))
{
throw error;
}
if (this != &rhs)
{
m_side = rhs.m_side;
m_average = rhs.m_average;
m_rolls = rhs.m_rolls;
m_num_sides = rhs.m_num_sides;
}
}
catch(...)
{
cout << "The '=' operation is only permissible with dice of the same type" << endl;
}
return *this;
}
Current Mood: geeky