Introduction for Rock-paper-scissor game in C++:
Rock-Paper-Scissors is a timeless hand game commonly employed as a basic method for making choices. Typically, this game involves two participants who simultaneously form one of three hand shapes - rock, paper, or scissors. The guidelines are simple: rock triumphs over scissors, scissors defeat paper, and paper wins against rock.
Developing a Rock-Paper-Scissors game in C++ serves as an excellent exercise for novice programmers to grasp essential coding principles like conditionals, loops, and input/output operations. This project offers practical exposure to fundamental C++ syntax and constructs, all while enjoying a bit of entertainment.
Image:
Game Rules To be Follow:
We have three scenarios to consider:
- Rock vs Paper -> Paper wins.
- Paper vs Scissor -> Scissor wins.
- Scissor vs Rock -> Rock wins.
Approach 1: Simple Approach
Implementation:
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
enum Choice { ROCK, PAPER, SCISSORS };
Choice getComputerChoice() {
return static_cast<Choice>(rand() % 3);
}
Choice getUserChoice() {
int choice;
cout << "Enter your choice (0 = Rock, 1 = Paper, 2 = Scissors): ";
cin >> choice;
return static_cast<Choice>(choice);
}
void printChoice(Choice choice) {
switch (choice) {
case ROCK:
cout << "Rock";
break;
case PAPER:
cout << "Paper";
break;
case SCISSORS:
cout << "Scissors";
break;
}
}
void determineWinner(Choice userChoice, Choice computerChoice) {
if (userChoice == computerChoice) {
cout << "It's a tie!" << endl;
} else if ((userChoice == ROCK && computerChoice == SCISSORS) ||
(userChoice == PAPER && computerChoice == ROCK) ||
(userChoice == SCISSORS && computerChoice == PAPER)) {
cout << "You win!" << endl;
} else {
cout << "You lose!" << endl;
}
}
int main() {
srand(static_cast<unsigned int>(time(0))); // Seed random number generator
Choice userChoice = getUserChoice();
Choice computerChoice = getComputerChoice();
cout << "You chose: ";
printChoice(userChoice);
cout << endl;
cout << "Computer chose: ";
printChoice(computerChoice);
cout << endl;
determineWinner(userChoice, computerChoice);
return 0;
}
Output:
Enter your choice (0 = Rock, 1 = Paper, 2 = Scissors): Rock
You chose: Rock
Computer chose: Paper
You lose!
Explanation:
- Step 1: Importing Libraries First, the program includes the necessary libraries The stream library is used for input and output operations, allowing us to interact with the user through the console. The cstdlib library is used for generating random numbers, which will help the computer make its choice. The ctime library is used to seed the random number generator with the current time, ensuring that the random choices are different each time the program runs.
- Step 2: Defining Choices An enum (enumeration) is defined to represent the three possible choices in the game: Rock, Paper, and Scissors. This makes the code more readable and manageable by using meaningful names instead of arbitrary numbers.
- Step 3: Generating the Computer's Choice A function is created to generate the computer's choice. This function uses the rand function to produce a random number between 0 and 2, each representing one of the three choices (Rock, Paper, or Scissors). After that, the random number is cast to the Choice enum.
- Step 4: Getting the User's Choice Another function is defined to get the user's choice. The program prompts the user to enter a number (0 for Rock, 1 for Paper, or 2 for Scissors). After that, this number is converted to the corresponding Choice enum.
- Step 5: Printing Choices A function is used to print the chosen option (Rock, Paper, or Scissors) in a readable format. Depending on the value of the Choice enum; the function outputs the appropriate string.
- Step 6: Determining the Winner A function is defined to determine the winner based on the rules of Rock-Paper-Scissors: If both the user and the computer choose the same option, the result is a tie. If the user's choice beats the computer's choice according to the game's rules (Rock beats Scissors, Paper beats Rock, Scissors beats Paper), the user wins. Otherwise, the computer wins.
- Step 7: Main Function Operations In the main function, the program starts by seeding the random number generator with the current time using the srand function. This ensures that the random choices are different each time the program runs.
- The stream library is used for input and output operations, allowing us to interact with the user through the console.
- The cstdlib library is used for generating random numbers, which will help the computer make its choice.
- The ctime library is used to seed the random number generator with the current time, ensuring that the random choices are different each time the program runs.
- If both the user and the computer choose the same option, the result is a tie.
- If the user's choice beats the computer's choice according to the game's rules (Rock beats Scissors, Paper beats Rock, Scissors beats Paper), the user wins.
- Otherwise, the computer wins.
Complexity analysis:
Time Complexity:
- Generating the Computer's Choice: This involves generating a random number, which is a constant time operation, O(1).
- Getting the User's Choice: Reading input from the user is also a constant time operation, O(1).
- Printing Choices: Printing two choices (user and computer) is another constant time operation, O(1).
- Determining the Winner: The winner is determined through a few conditional checks, which again operate in constant time, O(1).
Overall, the time complexity of the application is O(1) as every operation is executed in constant time.
Space Complexity:
Variable Storage:
- The user's choice is stored in a single variable.
- The computer's choice is stored in another variable.
- Additional memory is used for the functions and enums, but these are also fixed in size.
Enumerations and Constants:
The enumeration declaration for Rock, Paper, and Scissors remains compact and does not expand based on input size.
Input/Output Procedures:
The storage space necessary for input and output procedures is minimal and remains constant.
In general, the spatial efficiency of the software is O(1) as it utilizes a consistent memory allocation irrespective of the input magnitude.
Approach 2: Using Classes and Objects
In this method, we develop the Rock-Paper-Scissors game by applying object-oriented programming (OOP) concepts. By encapsulating the game's logic within a class, we establish a structured and adaptable design. This technique enhances code organization and encourages principles like encapsulation and abstraction.
Implementation of Classes and Objects:
#include <iostream>
#include <cstdlib>
#include <ctime>
class RockPaperScissorsGame {
private:
enum Choice { ROCK, PAPER, SCISSORS };
Choice getComputerChoice() {
return static_cast<Choice>(rand() % 3);
}
Choice getUserChoice() {
int choice;
std::cout << "Enter your choice (0 = Rock, 1 = Paper, 2 = Scissors): ";
std::cin >> choice;
return static_cast<Choice>(choice);
}
void printChoice(Choice choice) {
switch (choice) {
case ROCK: std::cout << "Rock"; break;
case PAPER: std::cout << "Paper"; break;
case SCISSORS: std::cout << "Scissors"; break;
}
}
void determineWinner(Choice userChoice, Choice computerChoice) {
if (userChoice == computerChoice) {
std::cout << "It's a tie!" << std::endl;
} else if ((userChoice == ROCK && computerChoice == SCISSORS) ||
(userChoice == PAPER && computerChoice == ROCK) ||
(userChoice == SCISSORS && computerChoice == PAPER)) {
std::cout << "You win!" << std::endl;
} else {
std::cout << "You lose!" << std::endl;
}
}
public:
void play() {
Choice userChoice = getUserChoice();
Choice computerChoice = getComputerChoice();
std::cout << "You chose: ";
printChoice(userChoice);
std::cout << std::endl;
std::cout << "Computer chose: ";
printChoice(computerChoice);
std::cout << std::endl;
determineWinner(userChoice, computerChoice);
}
};
int main() {
srand(static_cast<unsigned int>(time(0)));
RockPaperScissorsGame game;
game.play();
return 0;
}
Output:
Enter your choice (0 = Rock, 1 = Paper, 2 = Scissors): Rock
You chose: Rock
Computer chose: Rock
It's a tie!
Explanation:
- Step 1: Defining the Class We start by defining a class named RockPaperScissorsGame. A class in C++ is a blueprint for creating objects. It encapsulates data and functions that operate on that data.
- Step 2: Enumerating Choices Inside the class, we define an enumeration Choice that represents the three possible choices in the game: Rock, Paper, and Scissors. This makes the code more readable and easier to manage by using meaningful names instead of arbitrary numbers.
- Step 3: Generating the Computer's Choice We create a private method getComputerChoice within the class. This method uses the rand function to generate a random number between 0 and 2, each corresponding to Rock, Paper, or Scissors. After that, the random number is cast to the Choice enum.
- Step 4: Getting the User's Choice Another private method getUserChoice prompts the user to enter a number (0 for Rock, 1 for Paper, or 2 for Scissors). After that, the user's input is converted to the corresponding Choice enum.
- Step 5: Printing Choices We define a private method printChoice(Choice choice) that takes a Choice as an argument and prints the corresponding name (Rock, Paper, or Scissors). This method uses a switch statement to handle the conversion from the enum to a string representation.
- Step 6: Determining the Winner The private method determineWinner(Choice userChoice, Choice computerChoice) determines the winner based on the game rules: s If both choices are the same, it prints "It's a tie!". If the user's choice beats the computer's choice according to the game's rules (Rock beats Scissors, Paper beats Rock, Scissors beats Paper), it prints "You win!". Otherwise, it prints, "You lose!".
- Step 7: Playing the Game The play method is the public method that orchestrates the game. Calls getUserChoice to get the user's choice. Calls getComputerChoice to generate the computer's choice. Prints both choices using printChoice. Determines and prints the winner using determineWinner.
- Step 8: Main Function Operations In the main function, we seed the random number generator with the current time using srand(time(0)) to ensure different random choices each time the program runs. Then, we create an object of the RockPaperScissorsGame class and call its play method to start the game.
- If both choices are the same, it prints "It's a tie!".
- If the user's choice beats the computer's choice according to the game's rules (Rock beats Scissors, Paper beats Rock, Scissors beats Paper), it prints "You win!".
- Otherwise, it prints, "You lose!".
- Calls getUserChoice to get the user's choice.
- Calls getComputerChoice to generate the computer's choice.
- Prints both choices using printChoice.
- Determines and prints the winner using determineWinner.
Complexity analysis:
Time Complexity:
Generating the Computer's Choice:
The getComputerChoice function produces a random number in constant time, denoted as O(1).
Getting the User's Choice:
The getUserChoice function requests input from the user and reads it, both of which are operations with a constant time complexity of O(1).
Printing Choices:
The print option function displays a string depending on the enum value, with a time complexity of O(1), ensuring constant-time performance.
Determining the Winner:
The function to ascertain the victor employs several conditional evaluations to establish the winner, constituting a constant-time process denoted as O(1).
Playing the Game:
The play function invokes the preceding functions sequentially, with each performing in constant time, leading to a consistent time complexity of O(1).
Space Complexity:
Variable Storage:
The application utilizes several variables to save the user's selection, the computer's selection, and potentially some temporary variables within the functions. These variables have a set quantity and are not influenced by the size of input, hence they occupy a consistent amount of memory, denoted as O(1).
Enums and Constants:
The Choice enum and all constant values specified within the class remain unaltered in size regardless of the input size, thereby adding a consistent amount of space, denoted as O(1).
Input/Output Operations:
The amount of memory needed for input and output tasks (such as saving user entries, displaying on the screen) is very low and remains fixed at O(1).
Class Overhead:
The space required for declaring the class and its functions remains constant regardless of the input size, adding a fixed quantity of memory, denoted as O(1).
Approach 3: Using Arrays for Choices and Results
This method utilizes arrays to manage the options and outcomes, enhancing the code's conciseness and scalability.
Implementation of Arrays for Choices and Results:
#include <iostream>
#include <cstdlib>
#include <ctime>
const char* choices[] = { "Rock", "Paper", "Scissors" };
int getComputerChoice() {
return rand() % 3;
}
int getUserChoice() {
int choice;
std::cout << "Enter your choice (0 = Rock, 1 = Paper, 2 = Scissors): ";
std::cin >> choice;
return choice;
}
void determineWinner(int userChoice, int computerChoice) {
if (userChoice == computerChoice) {
std::cout << "It's a tie!" << std::endl;
} else if ((userChoice == 0 && computerChoice == 2) ||
(userChoice == 1 && computerChoice == 0) ||
(userChoice == 2 && computerChoice == 1)) {
std::cout << "You win!" << std::endl;
} else {
std::cout << "You lose!" << std::endl;
}
}
int main() {
srand(static_cast<unsigned int>(time(0)));
int userChoice = getUserChoice();
int computerChoice = getComputerChoice();
std::cout << "You chose: " << choices[userChoice] << std::endl;
std::cout << "Computer chose: " << choices[computerChoice] << std::endl;
determineWinner(userChoice, computerChoice);
return 0;
}
Output:
Enter your choice (0 = Rock, 1 = Paper, 2 = Scissors): Rock
You chose: Rock
Computer chose: Paper
You lose!
Explanation:
- Step 1: Importing Libraries We start by including the necessary libraries: stream for input and output operations. cstdlib for random number generation functions. ctime to seed the random number generator with the current time.
- Step 2: Defining Choices with Arrays We define an array of string choices that hold the three possible choices: "Rock", "Paper", and "Scissors". This array allows us to access and print the choices based on their index easily.
- Step 3: Generating the Computer's Choice We define the getComputerChoice function to generate a random choice for the computer. It uses the rand function to generate a random number between 0 and 2, which corresponds to the indices of the choices array.
- Step 4: Getting the User's Choice The getUserChoice function prompts the user to enter their choice as a number (0 for Rock, 1 for Paper, 2 for Scissors). After that, the user input is returned as an integer.
- Step 5: Determining the Winner The determineWinner function takes the user's choice and the computer's choice as arguments. It then compares these choices to determine the winner: If the choices are the same, it's a tie. If the user's choice beats the computer's choice according to the game rules, the user wins. Otherwise, the computer wins.
- Step 6: Main Function Operations In the main function, we seed the random number generator with the current time using srand(time(0)) to ensure different random choices each time the program runs.
- stream for input and output operations.
- cstdlib for random number generation functions.
- ctime to seed the random number generator with the current time.
- If the choices are the same, it's a tie.
- If the user's choice beats the computer's choice according to the game rules, the user wins.
- Otherwise, the computer wins.
Complexity analysis:
Time Complexity:
Generating the Computer's Choice:
The getComputerChoice function creates a random number by utilizing rand % 3, which operates in constant time, denoted as O(1).
Getting the User's Choice:
The getUserChoice function requests input from the user and reads it, which is also an operation that takes constant time, denoted as O(1).
Printing Choices:
Displaying the selections made by the user and the computer entails retrieving items from the choices array and displaying them, with both actions categorized as constant-time procedures, O(1).
Determining the Winner:
The function "determine winner" carries out several comparisons and displays a message according to the game rules, all of which are operations that take constant time, denoted as O(1).
Main Function Operations:
Tasks performed within the main function, such as invoking the functions and displaying outputs, are all completed in constant time complexity, denoted as O(1).
Thus, the program's time complexity remains O(1) since every operation runs in a constant time irrespective of the input's size.
Space Complexity:
Variable Storage:
The software utilizes several variables to hold the selections made by the user, the selections made by the computer, and the outcomes of the comparisons. These variables necessitate a consistent level of memory allocation, denoted as O(1).
Arrays:
The options array holds three immutable strings ("Rock", "Paper", "Scissors"), requiring a fixed space of O(1).
Enums and Constants:
There are no enumerations or constant variables employed in this particular setup apart from the selections array, each of which occupies a fixed space, denoted as O(1).
Input/Output Operations:
The amount of memory needed for both input (selected by the user) and output (displaying messages) tasks is minimal and remains constant, denoted as O(1).
Thus, the program's space complexity is O(1) since it utilizes a constant memory size regardless of the input's scale.