Reputation: 11
I'm trying to make a function for a rock, paper, scissors game with two char parameters where the first one represents the user's choice of rock, paper, or scissors. The second parameter represents the result of the game, either win, loss, or tie. When I tried to call the function, however, nothing is happening. I'm lost on what exactly I need to do next. All help is greatly appreciated!
#include <iostream>
#include <cstdlib>
using namespace std;
double playRPS (char a, char b);
int main() {
char letter;
char result = 0;
cout << "Welcome to COP3014 ROCK PAPER SCISSORS!\n\n";
cout << "Please select: " << endl
<< "Rock(r), Paper(p), or Scissors(s)? " << endl
<< "Or enter q to quit --> ";
cin >> letter;
if (letter == 'r' || letter == 'R' || letter == 'p' || letter == 'P' || letter == 's' || letter == 'S') {
playRPS(letter, result);
}
else {
cout << "Please enter r, p, or s" << endl;
}
return 0;
}
double playRPS (char x, char y) {
int choice1 = 0, choice2 = 0, choice3 = 0;
int user2 = rand() % 3 + 1;
if (( x == 'r' || x == 'R') && (user2 == '2')) {
cout << "The computer chose... PAPER!";
cout << "You chose ROCK!";
cout << "You LOSE!";
y = choice2;
return choice2;
}
else if ((x == 'r' || x == 'R') && (user2 == '1')) {
cout << "The computer chose... ROCK!";
cout << "You chose ROCK!";
cout << "You TIED!";
y = choice3;
return choice3;
}
else if ((x == 'r' || x == 'R') && (user2 == '3')) {
cout << "The computer chose... SCISSORS!";
cout << "You chose ROCK!";
cout << "You WIN!";
y = choice1;
return choice1;
}
else if (( x == 'p' || x == 'P') && (user2 == '2')) {
cout << "The computer chose... PAPER!";
cout << "You chose PAPER!";
cout << "You TIED!";
y = choice3;
return choice3;
}
else if (( x == 'p' || x == 'P') && (user2 == '1')) {
cout << "The computer chose... ROCK!";
cout << "You chose PAPER!";
cout << "You WIN!";
y = choice1;
return choice1;
}
else if (( x == 'p' || x == 'P') && (user2 == '3')) {
cout << "The computer chose... SCISSORS!";
cout << "You chose PAPER!";
cout << "You LOSE!";
y = choice2;
return choice2;
}
else if (( x == 's' || x == 'S') && (user2 == '2')) {
cout << "The computer chose... PAPER!";
cout << "You chose SCISSORS!";
cout << "You WIN!";
y = choice1;
return choice1;
}
else if (( x == 's' || x == 'S') && (user2 == '1')) {
cout << "The computer chose... ROCK!";
cout << "You chose SCISSORS!";
cout << "You LOSE!";
y = choice2;
return choice2;
}
else if (( x == 's' || x == 'S') && (user2 == '3')) {
cout << "The computer chose... SCISSORS!";
cout << "You chose SCISSORS!";
cout << "You TIED!";
y = choice3;
return choice3;
}
else{
return main();
}
Upvotes: 1
Views: 750
Reputation: 1914
General remarks
using namespace std;
return main();
You are not allowed to call main
in your code. This will result in Undefined Behavior. Plus, what is your intention here?
rand()
rand()
should be avoided. Here is an interesting video on why you should not use it, and instead use C++11 random.
y = choice2;
You are passing y
by value, which means assigning it won't modify the y
from the outside. You should pass y
by reference when doing this (i.e. char& y
in the declaration).
Why is the function not doing anything?
... Actually, it does!
user2 == '2'
Your comparisons are broken. '2'
is actually not 2
, but 50
. The reason is that '2'
is a character, so you actually are reading the associated character code.
This means all of your conditions are false in playRPS
, so the only thing the function does it to call main()
(in return main();
).
What about shortening your code?
Your test cases are quite redundant and heavy. You could change it to drastically cut down your code size.
Let's print what the choice selected by the player...
if (x == 'r' || x == 'R')
cout << "You chose ROCK!" << endl;
else if (x == 'p' || x == 'P')
cout << "You chose PAPER!" << endl;
else if (x == 's' || x == 'S')
cout << "You chose SCISSORS!" << endl;
All good! Let's do the same with the computer's choice!
if (user2 == 1)
cout << "The computer chose... ROCK!" << endl;
else if (user2 == 2)
cout << "The computer chose... PAPER!" << endl;
else if (user2 == 3)
cout << "The computer chose... SCISSORS!" << endl;
Then you should compare what the player chose to what the computer chose, and tell who is the winner. Unfortunately, we can't compare x
to user2
without doing many cases again...
What if we decided to have x
's choice being saved the same way as user2
? We also can use tolower
to avoid checking for the caps variant of the letter.
int user1 = 0;
x = tolower(x); // we force x to lower case
if (x == 'r')
user1 = 1;
else if (x == 'p')
user1 = 2;
else if (x == 's')
user1 = 3;
Good! Now we can also improve conditions in our first if
/else if
block:
if (user1 == 1)
cout << "You chose ROCK!" << endl;
else if (user1 == 2)
cout << "You chose PAPER!" << endl;
else if (user1 == 3)
cout << "You chose SCISSORS!" << endl;
Which means we also can compare user1
to user2
so we know who won.
if (user1 == user2) {
cout << "It's a TIE!" << endl;
}
else if ((user1 == 1 && user2 == 2) ||
(user1 == 2 && user2 == 3) ||
(user1 == 3 && user2 == 1)) {
cout << "You LOSE!" << endl;
}
else {
cout << "You WIN!" << endl;
}
However, using 1
, 2
and 3
does not make things very clear. What if you used an enum
to represent these values?
enum RPSChoice
{
ROCK = 1,
PAPER = 2,
SCISSORS = 3
};
For example, the first block now looks like:
if (user1 == ROCK)
cout << "You chose ROCK!" << endl;
else if (user1 == PAPER)
cout << "You chose PAPER!" << endl;
else if (user1 == SCISSORS)
cout << "You chose SCISSORS!" << endl;
What if we wrapped our new two first blocks into a function so we avoid repeating ourselves?
void printDecision(string who, int choice) {
cout << who; // no matter what, we will tell who took a decision
if (choice == ROCK)
cout << " chose ROCK!" << endl;
else if (choice == PAPER)
cout << " chose PAPER!" << endl;
else if (choice == SCISSORS)
cout << " chose SCISSORS!" << endl;
}
This way, we can make playRPS
even more clear, by replacing the two large blocks into simple, short function calls:
printDecision("You", user1);
printDecision("The computer", user2);
Let's do another simple function that decides who won:
int winner(int user1, int user2) {
if (user1 == user2) {
return 0; // tie
}
else if ((user1 == ROCK && user2 == PAPER) ||
(user1 == PAPER && user2 == SCISSORS) ||
(user1 == SCISSORS && user2 == ROCK)) {
return 2; // user2 is the winner
}
else {
return 1; // user1 is the winner
}
}
And a final one that returns the value we give according to a given character:
int characterToChoice(char c)
{
c = tolower(c);
if (c == 'r')
return ROCK;
else if (c == 's')
return SCISSORS;
else if (c == 'p')
return PAPER;
else
return 0; // Not a proper choice!
}
Done! This is the final program with all improvements in (nothing done to replace rand()
in), and here is an online prompt to try it out.
Note that there are more ways you can improve the code, to simplify it even more and to make it more clear. I am most notably thinking about std::unordered_map to bind a RPSChoice
value to a string
, and a char
to a RPSChoice
. You may also prefer switch to if
in some cases.
As stated by the comments to your question, you could have diagnosed this issue using a debugger. πάντα ῥεῖ's comment for reference:
The right tool to solve such problems is your debugger. You should step through your code line-by-line before asking on Stack Overflow. For more help, please read How to debug small programs (by Eric Lippert).
Upvotes: 6