Instructions
Requirements and Specifications
Source Code
#include
#include
#include
#include
#include
#include
using namespace std;
// Define here some constants that will be used during the game
const int OUTCOME_AWINS = 1;
const int OUTCOME_BWINS = 2;
const int OUTCOME_DRAW = 3;
const int ROCK = 1;
const int PAPER = 2;
const int SCISSORS = 3;
const int PLAYER_VS_CPU = 1;
const int CPU_VS_CPU = 2;
// Functions identifiers
int getOutcome(int,int);
int getHand();
void runGame(int);
void printTable(int[], int, int);
void writeTable(ofstream&, int[], int, int);
string getHandName(int);
// Main
int main() {
// Ask user for a game mode
int GAME_MODE;
while(true) {
cout << "Select game mode:" << endl;
cout << "\t1) Player vs. Computer" << endl;
cout << "\t2) Computer vs. Computer" << endl;
cin >> GAME_MODE;
if(GAME_MODE >= PLAYER_VS_CPU && GAME_MODE <= CPU_VS_CPU) {
break;
} else {
cout << "Invalid option." << endl;
}
}
// Start game
runGame(GAME_MODE);
return 0;
}
int getOutcome(int playerAHand, int playerBHand) {
/**
* This function returns the outcome of a ROCK, PAPER, SCISSORS round
*
*/
// Conditions for playerA to win
if((playerAHand == ROCK && playerBHand == SCISSORS)
||(playerAHand == PAPER && playerBHand == ROCK)
|| (playerAHand == SCISSORS && playerBHand == PAPER)) {
return OUTCOME_AWINS;
} else if((playerBHand == ROCK && playerAHand == SCISSORS)
||(playerBHand == PAPER && playerAHand == ROCK)
|| (playerBHand == SCISSORS && playerAHand == PAPER)) {
return OUTCOME_BWINS;
} else {
return OUTCOME_DRAW;
}
}
int getHand() {
/**
* @brief This function displays the options to user and prompt for one option
* The function keeps prompting the user until s/he enters a valid option
*
*/
int option;
while(true) {
cout << "1) Rock \n2) Paper\n3)Scissors\nPlease choose:";
cin >> option;
if(option >= ROCK && option <= SCISSORS) {
return option;
} else {
cout << "Invalid option." << endl;
}
}
}
void runGame(int GAME_MODE) {
/**
* @brief In this function all game functionalities are managed
*
*/
// Counter for number of rounds
int rounds = 0;
// Array to store outcomes from each round
int outcomes[100];
// Get player names
string playerAName = "User";
string playerBName = "CPU";
if(GAME_MODE == CPU_VS_CPU) {
playerAName = "CPU1";
playerBName = "CPU2";
}
// Now, begin with game
int playerAHand, playerBHand, outcome;
int playerARoundsWon = 0;
int playerBRoundsWon = 0;
int finalOutcome;
while(true) {
// Start round
cout << "ROUND: " << rounds+1 << endl;
// First, player A
if(GAME_MODE == PLAYER_VS_CPU) {
// As user for option
playerAHand = getHand();
cout << playerAName << " chose " << getHandName(playerAHand) << endl;
} else {
// Chose random
playerAHand = ROCK + (rand() % SCISSORS - ROCK + 1);
cout << playerAName << " chose " << getHandName(playerAHand) << endl;
}
// Choose playerBHand
playerBHand = ROCK + (rand() % SCISSORS - ROCK + 1);
cout << playerBName << " chose " << getHandName(playerBHand) << endl;
// Get outcome
outcome = getOutcome(playerAHand, playerBHand);
if(outcome == OUTCOME_AWINS) {
cout << playerAName << " wins the round!" << endl;
playerARoundsWon++;
rounds++;
} else if(outcome == OUTCOME_BWINS) {
cout << playerBName << " wins the round!" << endl;
playerBRoundsWon++;
rounds++;
} else {
// draw
cout << "It is a draw!" << endl;
}
cout << endl;
if(outcome != OUTCOME_DRAW) {
outcomes[rounds] = outcome;
}
// Check for a winner
if(rounds > 1 && rounds%2 != 0) // odd number of rounds
{
// Check for percentages
double percentageA = (double)playerARoundsWon / (float)rounds;
double percentageB = (double)playerBRoundsWon / (float)rounds;
if(percentageA > 0.5) {
finalOutcome = OUTCOME_AWINS;
break;
} else if(percentageB > 0.5) {
finalOutcome = OUTCOME_BWINS;
break;
}
//cout << percentageA << " " << percentageB << endl;
}
}
// Finally, print table
printTable(outcomes, rounds, GAME_MODE);
// Ask user if s/he wants to save the results
int option;
string filename;
auto t = std::time(nullptr);
auto tm = *std::localtime(&t);
ostringstream os;
os << playerAName << "_" << playerBName << "_Results_" << std::put_time(&tm, "%M-%d-%Y-%H-%M") << ".txt";
filename = os.str();
while(true) {
cout << "Do you want to save the results? (1 = yes, 2 = no): ";
cin >> option;
if(option == 1) {
// Open file
ofstream file;
file.open(filename, ios::out);
writeTable(file, outcomes, rounds, GAME_MODE);
cout << "Results saved to " << filename << endl;
file.close();
break;
} else if(option == 2) {
break;
} else {
cout << "Invalid option." << endl;
}
}
}
void printTable(int outcomes[], int rounds, int GAME_MODE) {
/**
* @brief This function prints the results from each round in a well formatted table
*
*/
// Declare the name of players based on the game mode
string playerAName = "User";
string playerBName = "CPU";
if(GAME_MODE == CPU_VS_CPU) {
playerAName = "CPU1";
playerBName = "CPU2";
}
// Print headers
cout << left << setw(15) << "Round" << right << setw(15) << "|" << playerAName << right << setw(15) << "|" << playerBName << endl;
cout << "-----------------------------------------------------------------------" << endl;
string playerAOutcome, playerBOutcome;
int playerARoundsWon = 0;
int playerBRoundsWon = 0;
// Print the results for each round
for(int i = 0; i < rounds; i++) {
if(outcomes[i] == OUTCOME_AWINS) {
playerAOutcome = "W";
playerBOutcome = "L";
playerARoundsWon++;
} else if(outcomes[i] == OUTCOME_BWINS) {
playerAOutcome = "L";
playerBOutcome = "W";
playerBRoundsWon++;
} else if(outcomes[i] == OUTCOME_DRAW) {
playerAOutcome = "D";
playerBOutcome = "D";
}
cout << left << setw(15) << (i+1) << right << setw(15) << "|" << playerAOutcome << right << setw(19) << "|" << playerBOutcome << endl;
}
cout << endl;
// Print winner of game
if(playerARoundsWon > playerBRoundsWon) {
cout << "Winner: " << playerAName << endl;
} else {
cout << "Winner: " << playerBName << endl;
}
}
void writeTable(ofstream& os, int outcomes[], int rounds, int GAME_MODE) {
/**
* @brief This function write to a file the results from each round in a well formatted table
*
*/
// Print table
string playerAName = "User";
string playerBName = "CPU";
if(GAME_MODE == CPU_VS_CPU) {
playerAName = "CPU 1";
playerBName = "CPU 2";
}
os << left << setw(15) << "Round" << right << setw(15) << "|" << playerAName << right << setw(15) << "|" << playerBName << endl;
os << "-----------------------------------------------------------------------" << endl;
string playerAOutcome, playerBOutcome;
int playerARoundsWon = 0;
int playerBRoundsWon = 0;
for(int i = 0; i < rounds; i++) {
if(outcomes[i] == OUTCOME_AWINS) {
playerAOutcome = "W";
playerBOutcome = "L";
playerARoundsWon++;
} else if(outcomes[i] == OUTCOME_BWINS) {
playerAOutcome = "L";
playerBOutcome = "W";
playerBRoundsWon++;
} else if(outcomes[i] == OUTCOME_DRAW) {
playerAOutcome = "D";
playerBOutcome = "D";
}
os << left << setw(15) << (i+1) << right << setw(15) << "|" << playerAOutcome << right << setw(19) << "|" << playerBOutcome << endl;
}
os << endl;
if(playerARoundsWon > playerBRoundsWon) {
os << "Winner: " << playerAName << endl;
} else {
os << "Winner: " << playerBName << endl;
}
}
string getHandName(int playerHand) {
/**
* @brief Returns the name of a hand based on its value
*
*/
string name = "";
if(playerHand == ROCK) {
name = "Rock";
} else if(playerHand == PAPER) {
name = "Paper";
} else {
name = "Scissors";
}
return name;
}