Rock Paper Scissors

So for a homework assignment I'm supposed to create a simple rock-paper-scissors game.

here is a list of requirements and hints from my teacher:
Requirements:
(1) Your program should provide a simple user interface to tell the user when to choose a shape.
(2) The user will use the keyboard to choose a shape.
(3) The user will use the key ‘R’ (or ‘r’) to choose rock, the key ‘P’ (or ‘p’) to choose paper, and the key ‘S’ (or ‘s’) to choose scissor.
(4) Your program should work no matter the user types an uppercase letter (‘R’, ‘P’, or ‘S’) or a lowercase letter (‘r’, ‘p’, or ‘s’).
(5) If the user types any key that is not one of the above keys, your program should show a message and terminate.
(6) Your program should let the computer randomly choose a shape.
(7) Your program should display what shape the human player chose as well as what shape the AI player chose.
(8) Your program must be able to judge who wins (or if it’s a draw) and display the result.

Hints:
(1) To make sure the computer generates a random number, you need to include these header files:
#include <cstdlib> ← for rand() and srand()
#include <ctime> ← for time()
You also need to add this statement before you begin to use rand() to generate the random number:
srand( static_cast<unsigned int> ( time(0) ) );
(2) Use % operator to constrain the range of the random numbers.
For example, rand() % 3.


Anyway we have to use if statements not switch statements. So my code compiles just fine, but I guess there's something wrong with my logical operators or my rand number? Anyway I've tried a bunch of different things and can't seem to figure it out.

currently my output looks like this:
Rock-Paper-Scissors Game!
Please choose your symbol:
R for rock; P for paper; S for scissor: S
The computer chose Rock.
The match is a draw!
The computer chose Rock.
Victory!
The computer chose Paper.
Victory!
Press any key to continue . . .


Also my else statement doesn't work at the end so like if someone enter 'x' it still comes back with some output like that.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
  #include <iostream>
#include <cmath>
#include <ctime>
#include <cstdlib>
using namespace std;

//*******************************************************************************************************

int main()
{
	char human;
	int	ai;
	srand(static_cast<unsigned int> (time(0)));
	ai = (rand() % 3) + 1;
	cout << "Rock-Paper-Scissors Game!" << endl;
	cout << "Please choose your symbol:" << endl;
	cout << "R for rock; P for paper; S for scissor: ";
	cin >> human;
	if ((human == 'R' || human == 'r') && (ai == 1))
	{
		cout << "The computer chose Paper." << endl;
		cout << "You lose better luck next time!" << endl;
	}
	else if ((human == 'R' || human == 'r') && (ai == 3))
	{
		cout << "The computer chose Rock." << endl;
		cout << "The match is a draw!" << endl;
	}
	else if ((human == 'R' || human == 'r') && (ai == 2))
	{
		cout << "The computer chose Scissors." << endl;
		cout << "Victory!" << endl;
	}
	else if ((human == 'P' || human == 'p') && (ai == 1))
	{
		cout << "The computer chose Paper." << endl;
		cout << "The match is a draw!" << endl;
	}
	else if ((human == 'P' || human == 'p') && (ai == 3))
	{
		cout << "The computer chose Rock." << endl;
		cout << "Victory!" << endl;
	}
	else if ((human == 'P' || human == 'p') && (ai == 2))
	{
		cout << "The computer chose Scissors." << endl;
		cout << "You lose better luck next time!" << endl;
	}
	else if ((human == 'S' || human == 's') && (ai == 1))
	{
		cout << "The computer chose Paper." << endl;
		cout << "Victory!" << endl;
	}
	else if ((human == 'S' || human == 's') && (ai == 3))
	{
		cout << "The computer chose Rock." << endl;
		cout << "You lose better luck next time!" << endl;
	}
	else if ((human == 'S' || human == 's') && (ai == 2))
	{
		cout << "The computer chose Scissors." << endl;
		cout << "The match is a draw!" << endl;
	}
	else
	{
		cout << "Invalid input, Game Over." << endl;
	}
	return 0;

}

//*******************************************************************************************************
Last edited on
Anyone got any ideas why its not working??
I couldnt see anything so I actually compiled and ran and tested it. I get the correct answer every time.

Delete your executable and objects and do a complete total re-build of your code and see if it is an old version of a bug that you have since fixed causing the problems.

Thank you! it works just fine now but can you explain to me like how come it wasn't working even though the code was fine?
compilers and IDEs etc try to be smart by keeping untouched files rather than re-compile and re-build them. If you forget to compile, or the tool becomes confused, or other things like that, it can leave an old version out there. Sometimes, the only fix is to clean and rebuild the whole thing. Its something you learn to do with experience ... if you make a change to code and nothing changes in the output, before trying to debug more, recompile the thing.

Even if your code, it’s fine, you could consider that…

Anyway we have to use if statements not switch statements.

Tthat’s leads up to two possible hypotheses:
1) your teacher is a sadistic;
2) there’s some trick that s/he hopes you’ll be able to work out by yourselves.

Even if I would entertain the first one as the most probable, it could be worth take a glance to the second.

How does the rock-paper-scissors game work? Let’s keep the different choices the players can opt for in that fixed order (rock-paper-scissors – anyway every order would be fine) and give them a number:
rock --> 1
paper --> 2
scissors --> 3
(if you know about enumeration, well... )
We can now try to evaluate winning/losing situation by numbers instead of by words. It could sound masochistic at first glance, but numbers can take advantage of arithmetics, what words can’t (easily) do ;-)

Let’s build a table of possible combinations:
Pl. A Pl. B
rock rock 1-1 = 0 draw
rock paper 1-2 = -1 B wins
rock scissors 1-3 = -2 A wins
paper rock 2-1 = 1 A wins
paper paper 2-2 = 0 draw
paper scissors 2-3 = -1 B wins
scissors rock 3-1 = 2 B wins
scissors paper 3-2 = 1 A wins
scissors scissors 3-3 = 0 draw


What does this table tell us?
1) whenever the result is 0, it’s a draw
2) A wins when the result is: -2, 1, 1
3) B wins when the result is: -1, -1, 2

That means that there aren’t overlapping cases, and we could legitimately think that there’s a way of making the code work with just 3 if(s).
Last edited on
Thanks very much for the help and info. And just so I understand you're basically saying I could have all the win's in one if statement, all the draw's in one if statement, and all the lose's in another if statement?

And we couldn't use switch because at the time the assignment was given we hadn't learned about switch yet.
I could have all the win's in one if statement, all the draw's in one if statement, and all the lose's in another if statement?

Yes.

And we couldn't use switch because at the time the assignment was given we hadn't learned about switch yet.

Oh, I see... no sadism involved... Well, never judge a book from the cover :-)
yes, you can make this program super simple.
another way is you could have a 2 input lookup table with the answers. That wouldn't even need any logic.

@jonnin
Ok, that’s embarrassing :-)
It’s been quite easy to work out a solution with one table and two indexes, one for Player A (or ai) and one for Player B (or human), but I couldn’t figure out a solution with two tables :-(
I know I shouldn’t keep alive this thread, since it’s already been marked as solved, but if you could give me at least some hint I’d be grateful.

Thank you a lot.
you only need one table, sorry. It was obvious in MY mind what to do.

enum
{
R,P,S,maxrps //This is an old trick but if you insert a value before max it will resize your arrays automatically upon compile :) no need for this here, of course.
};


char winloseordraw[maxrps][maxrps]; //computer, human

winloseordraw[R][R] = 'D';
winloseordraw[R][P] = 'W';
winloseordraw[R][S] = 'L';
winloseordraw[P][R] = 'L';
winloseordraw[P][S] = 'W';
winloseordraw[P][P] = 'D';
winloseordraw[S][R] = 'W';
winloseordraw[S][P] = 'L';
winloseordraw[S][S] = 'D';

--------------------------
blah blah blah...
result = winloseordraw[computermove][humanmove];

you can make them 3d and put the words in, even fancy like "YOU WIN!!!"

looks like
char winloseordraw[maxrps][maxrps][20]; //computer, human
strcpy(winloseordraw[S][S], "Draw");

and you can go all in and make a vector of vectors of strings if you want. Its the concept that I am pushing here, not the code.

You can make the assignment of the table smaller and simpler also, but it makes it harder to read, not easier. Replacing the dozen if statements with this makes it easier to read, though, and much higher performance (not that it matters, but doing 1 thing vs checking 20 things). Keep this in mind as you grow and learn. People fall back on their early teachings --- ive seen professionals code a recursive factorial because that is how they did it in school, when a lookup with 25 or so values hard-coded is so much cleaner. THINK about what you are doing and how to do it with less processing. It will bear fruit when you get into large heavy programs.

If you had 2 human players on a network playing this thing, (now there is an image, the rock paper scissors MMO..) and you needed to check the answer in both directions, then you could have 2 tables.
or you could be a wiseguy and flip the index.

result for player1 = winloseordraw[p2in][p1in];
result for player2 = winloseordraw[p1in][p2in]; //think of computer index as "opponent" now.

It takes time and experience to see that kind of thing. But you can't unsee it once you understand, so youll get there.



I'm not going to go into how you can condense it if-wise using a karnaugh map. I sort of half-did that in another thread, basically factored out "paper" and made it into 2 sets of simplified ifs. You can take that deeper. Someone above me alluded to this numerically.


Last edited on
a 2 input lookup table
you only need one table

Oh, my goodness, I definitely got the wrong end of the stick! “A” table with 2 inputs. I don’t know how I could misunderstand your sentence, except because I’m even worst at English than at C++.
You can’t imagine how many hours I spent trying to work out a two tables solution :-D :-D

Thanks a lot for all your explanation and advice, I read them carefully and I found them really informative.
Topic archived. No new replies allowed.