This code implements the basics of the keno lottery game which are:
- There are a total of 60 numbers from 1 to 60 to be picked by the player
- The player can pick 5 to 10 numbers in a game round
- The computer picks 15 random numbers
- Depending on how many numbers are common between the player and the computer chosen numbers, an award is given to the player
- There is also a quick pick functionality, which enables the computer to pick numbers on behalf of the player if he wants
- Maintain credits balance
- 0 balance no game play allowed
- Provide insert credit functionality
- Take a bet input from the player for every game round
Please review the code and let me know the areas of improvement. I have just started learning C++ and this is my first standalone program.
#include <iostream>
#include <vector>
#define MIN_PICK_VALUE 1
#define MAX_PICK_VALUE 60
#define COMPUTER_PICK_COUNT 15
using namespace std;
class RandomNumber{ // Random number generator
public:
static int randomNumberGenerator(int min, int max){
return (rand() % max + min);
}
};
class KenoWinCalculator{
private:
vector<int> m_playerPick; // vector is used because the size is not fixed,
int m_ComputerPick[COMPUTER_PICK_COUNT] ={0}; // player can choose any picks between 5 and 10 but computer's is fixed
int m_hits = 0;
public:
KenoWinCalculator(const vector<int> &playerPick){
for(int i = 0 ; i < playerPick.size() ; ++i) // Update player picked values
m_playerPick.push_back(playerPick[i]);
}
void generateComputerPick(){ // Generate 10 unique computer picked random values
int rngValue =0, i =0;
while(i < COMPUTER_PICK_COUNT){
nextRng:
rngValue = RandomNumber::randomNumberGenerator(MIN_PICK_VALUE, MAX_PICK_VALUE);
for(int j =0; j < i; ++j)
{
if(m_ComputerPick[j] == rngValue) // check if the generated rng value is not unique
goto nextRng;
}
m_ComputerPick[i] = rngValue;
++i;
}
}
void calculateHits(){ // Calculates no of common nos between player and computer pick
for(int playerPickCount = 0; playerPickCount < m_playerPick.size();
++playerPickCount)
for(int compPickCount = 0; compPickCount
< sizeof(m_ComputerPick)/sizeof(m_ComputerPick[0]); ++compPickCount){
if(m_playerPick[playerPickCount] == m_ComputerPick[compPickCount])
++m_hits;
}
}
int getHitValue() const{
return m_hits;
}
int getPlayerPickCount() const{
return static_cast<int>(m_playerPick.size());
}
const vector<int>& getPlayerPickValues(){
return m_playerPick;
}
int* getComputerPick(){
return m_ComputerPick;
}
};
class Bank{
private:
int m_bet;
int m_bankBalance;
public:
Bank(): m_bet(0), m_bankBalance(0){} // this class maintains bet and player credit meter
void setBet(int betValue){
m_bet = betValue;
}
void setBankBalance(int balance){
m_bankBalance += balance;
}
void updatebankBalance(){
m_bankBalance -= m_bet;
}
int getBankBalance() const{
return m_bankBalance;
}
bool isEnoughBalanceToPlayGame(){
return m_bankBalance >= m_bet;
}
bool isBetValid(){
return m_bet <= m_bankBalance && m_bet > 0;
}
friend class Award;
};
class Award{
private: // This class maintains pay table
int m_picks;
int m_hits;
enum Hit{
HIT_3 = 3,
HIT_4,
HIT_5,
HIT_6,
HIT_7,
HIT_8,
HIT_9,
HIT_10
};
enum Player_pick{
PICK_5 = 5,
PICK_6,
PICK_7,
PICK_8,
PICK_9,
PICK_10
};
public:
Award(const KenoWinCalculator &calc){
m_picks = calc.getPlayerPickCount();
m_hits = calc.getHitValue();
}
void awardWon(Bank &bank){
int amtWon = 0;
bool gameLost = false;
switch(m_picks){
case PICK_5: if(m_hits == HIT_5)
amtWon = 100;
else if(m_hits == HIT_4)
amtWon = 50;
else
gameLost = true;
break;
case PICK_6: if(m_hits == HIT_6)
amtWon = 150;
else if(m_hits == HIT_5)
amtWon = 120;
else if(m_hits == HIT_4)
amtWon = 100;
else
gameLost = true;
break;
case PICK_7: if(m_hits == HIT_7)
amtWon = 150;
else if(m_hits == HIT_6)
amtWon = 120;
else if(m_hits == HIT_5)
amtWon = 100;
else if(m_hits == HIT_4)
amtWon = 90;
else if(m_hits == HIT_3)
amtWon = 80;
else
gameLost = true;
break;
case PICK_8:if(m_hits == HIT_8)
amtWon = 175;
else if(m_hits == HIT_7)
amtWon = 150;
else if(m_hits == HIT_6)
amtWon = 120;
else if(m_hits == HIT_5)
amtWon = 100;
else if(m_hits == HIT_4)
amtWon = 90;
else if(m_hits == HIT_3)
amtWon = 80;
else
gameLost = true;
break;
case PICK_9:if(m_hits == HIT_9)
amtWon = 200;
else if(m_hits == HIT_8)
amtWon = 175;
else if(m_hits == HIT_7)
amtWon = 150;
else if(m_hits == HIT_6)
amtWon = 120;
else if(m_hits == HIT_5)
amtWon = 100;
else if(m_hits == HIT_4)
amtWon = 90;
else if(m_hits == HIT_3)
amtWon = 80;
else
gameLost = true;
break;
case PICK_10:if(m_hits == HIT_10)
amtWon = 250;
else if(m_hits == HIT_9)
amtWon = 200;
else if(m_hits == HIT_8)
amtWon = 175;
else if(m_hits == HIT_7)
amtWon = 150;
else if(m_hits == HIT_6)
amtWon = 120;
else if(m_hits == HIT_5)
amtWon = 100;
else if(m_hits == HIT_4)
amtWon = 90;
else if(m_hits == HIT_3)
amtWon = 80;
else
gameLost = true;
break;
}
if(!gameLost){
cout << "You won $" << amtWon << endl;
bank.m_bankBalance += amtWon;
}
else
cout << "You lost " << endl;
}
};
void kenoGameplay(Bank &credits){
#define QUIT_VALUE 100
#define MAX_NOS_PICKED 10
#define MIN_NOS_PICKED 5
vector<int> nosPicked;
int num = 0, numCount = 0;
bool isPlayerPickExisting;
char quickPick;
cout << "Do you want computer to pick nos for you? [y]es or [n]o" << endl;
cin >> quickPick;
cin.ignore(numeric_limits<streamsize>::max(),'\n');
if(quickPick != 'y'){
cout << "Pick atleast 5 and max 10 nos between 1 and 60...Enter 100 to QUIT entering nos\n";
while(num != QUIT_VALUE && numCount < MAX_NOS_PICKED){
cin >> num;
cin.ignore(numeric_limits<streamsize>::max(),'\n');
if(num == QUIT_VALUE && numCount < MIN_NOS_PICKED){ // Play game without picking enough nos
cout << "Game cannot be played. Please pick more nos. \n";
num = 0; // Reset num to avoid quiting game
}
else if(num == QUIT_VALUE && numCount >= MIN_NOS_PICKED) // Play game with enough nos picked
break;
else{
if(num >= MIN_PICK_VALUE && num <= MAX_PICK_VALUE){
isPlayerPickExisting = false;
for(int i = 0; i < nosPicked.size(); ++i)
{
if(num == nosPicked[i]){
cout << "Number picked already exist. Please select another no. \n";
isPlayerPickExisting = true;
}
}
if(!isPlayerPickExisting){
nosPicked.push_back(num);
++numCount;
}
}
else
cout << "You entered invalid no. Please try again \n";
}
} // end of while loop
}
else{
int quickPickCount = 0; // this code implements quick pick functionality
cout << "How many nos you want computer to pick (5-10)?" << endl;
cin >> quickPickCount;
cin.ignore(numeric_limits<streamsize>::max(),'\n');
while(quickPickCount < MIN_NOS_PICKED || quickPickCount > MAX_NOS_PICKED){
cout << "Invalid count value. Choose between 5 and 10 only. " << endl;
cin >> quickPickCount;
cin.ignore(numeric_limits<streamsize>::max(),'\n');
}
int rngValue =0, i =0;
while(i < quickPickCount){
nextRng:
rngValue = RandomNumber::randomNumberGenerator(MIN_PICK_VALUE, MAX_PICK_VALUE);
for(int j =0; j < i; ++j)
{
if(nosPicked[j] == rngValue) // check if the generated rng value is not unique
goto nextRng;
}
nosPicked.push_back(rngValue);
++i;
}
}
KenoWinCalculator winCalc(nosPicked);
winCalc.generateComputerPick();
winCalc.calculateHits();
Award wonAward(winCalc);
wonAward.awardWon(credits);
vector<int> playerPickedValues;
playerPickedValues = winCalc.getPlayerPickValues();
cout << "Your selection: \t";
for(int i = 0; i < playerPickedValues.size(); ++i) // display player selected values
cout << playerPickedValues[i] << " ";
cout << "\n";
int *computerPickedValues = winCalc.getComputerPick(); // display computer selected values
cout << "Computer selection: \t";
for(int i = 0; i < COMPUTER_PICK_COUNT; ++i)
cout << computerPickedValues[i] << " ";
cout << "\n";
cout << "no of hits: " << winCalc.getHitValue() << endl; // display no of hits and bank balance
cout << "Your bank balance is: $" << credits.getBankBalance() << endl;
}
int main() {
#define INSERT_MONEY 1
srand(static_cast<unsigned int>(time(0)));
cout << "******** WELCOME TO WORLD OF KENO ************** \n \n" << endl;
cout << "Please enter your name \n";
std::string name;
cin >> name;
cout << "Hello! " << name << "...\n\n";
char continueGameplay = 'y';
Bank credits;
int insertMoneyReduceBet = 0, bet = 0;
int insertMoney =0;
cout << "Please insert money " << endl;
cin >> insertMoney;
cin.ignore(numeric_limits<streamsize>::max(),'\n'); // flush cin buffer
credits.setBankBalance(insertMoney);
bool isBetInvalid = true;
while(continueGameplay != 'n'){
if(credits.isEnoughBalanceToPlayGame() || isBetInvalid == true){ // check if enough balance to play game
cout << "Place bet " << endl; // need bet input from player in case of bet reduction
cin >> bet;
cin.ignore(numeric_limits<streamsize>::max(),'\n'); // flush cin buffer
credits.setBet(bet);
isBetInvalid = false;
if(credits.isBetValid()){
credits.updatebankBalance();
kenoGameplay(credits);
cout << "GAME OVER \n";
cout << "Do you want to play another round \n";
cout << "'y' to continue and 'n' to quit playing \n";
cin >> continueGameplay;
}
else
cout << "Invalid bet value." << endl;
}
else{
cout << "Not enough balance/valid bet. Please insert money( press 1) or place valid bet(press 2) to max bank balance "<< credits.getBankBalance() << endl;
cin >> insertMoneyReduceBet;
if(insertMoneyReduceBet == INSERT_MONEY){
cout << "Insert money " << endl;
cin >> insertMoneyReduceBet;
credits.setBankBalance(insertMoneyReduceBet);
}
else
isBetInvalid = true;
}
}
return 0;
}