Rock Paper Scissors

Hi!

I am reviewing the things I learned in the first half of my CPP class for this upcoming semester.

How can I put this in a function?
std::cout << "Player choose (R-rock, P-paper, or S-scissors)? ";
std::cin >> userInput;
userInput = toupper(userInput);


Also, any suggestions on optimizing the following code:

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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#include <iostream>
#include <string>
#include <ctime>

void computerChoice(int choice)
{
	switch (choice)
	{
		case 0: std::cout << "Computer randomly played rock.\n";
			break;
		case 1: std::cout << "Computer randomly played paper.\n";
			break;
		case 2: std::cout << "Computer randomly played scissors.\n";
			break;
	}
}
void score(int WIN, int LOSE)
{
	std::cout << "User Score: " << WIN << "\nComputer Score: " << LOSE << std::endl;
}

//char userPrompt(char input)
//{
//	std::cout << "Player choose (R-rock, P-paper, or S-scissors)? ";
//	std::cin >> input;
//	return input;
//}

int main()
{
	srand(time(0));
	char userInput = ' ';
	int computerInput;
	char repeat;

	int win = 0;
	int lose = 0;

	do
	{
		std::cout << "----------------------------------------------\n";
		std::cout << "Player choose (R-rock, P-paper, or S-scissors)? ";
		std::cin >> userInput;
		userInput = toupper(userInput);

		while (userInput != 'R' && userInput != 'P' && userInput != 'S')
		{
			std::cout << "ERROR-1A: Must be a character from the list of 'R', 'P', or 'S'.\n";
			std::cout << "Player choose (R-rock, P-paper, or S-scissors)? ";
			std::cin >> userInput;
			userInput = toupper(userInput);

			if (userInput == 'R' || userInput == 'P' || userInput == 'S')
				break;
		}

		std::cout << "\n";

		while (true)
		{
			computerInput = rand() % 10;
			if (computerInput == 0 || computerInput == 1 || computerInput == 2)
				break;
		}


		if (userInput == 'R' && computerInput == 0)
		{
			computerChoice(computerInput);
			score(win, lose);
		}
		else if (userInput == 'R' && computerInput == 1)
		{
			lose++;
			computerChoice(computerInput);
			score(win, lose);
		}
		else if (userInput == 'R' && computerInput == 2)
		{
			win++;
			computerChoice(computerInput);
			score(win, lose);
		}
		else if (userInput == 'P' && computerInput == 0)
		{
			lose++;
			computerChoice(computerInput);
			score(win, lose);
		}
		else if (userInput == 'P' && computerInput == 1)
		{
			computerChoice(computerInput);
			score(win, lose);
		}
		else if (userInput == 'P' && computerInput == 2)
		{
			lose++;
			computerChoice(computerInput);
			score(win, lose);
		}
		else if (userInput == 'S' && computerInput == 0)
		{
			lose++;
			computerChoice(computerInput);
			score(win, lose);
		}
		else if (userInput == 'S' && computerInput == 1)
		{
			win++;
			computerChoice(computerInput);
			score(win, lose);
		}
		else if (userInput == 'S' && computerInput == 2)
		{
			computerChoice(computerInput);
			score(win, lose);
		}


		std::cout << "\nPlay again (Y-yes || N-no)? ";
		std::cin >> repeat;
		std::cout << "\n";
		repeat = toupper(repeat);

		while (repeat != 'Y' && repeat != 'N')
		{
			std::cout << "Invalid input. Must be Y || N only.\n";
			std::cout << "Play again (Y-yes || N-no)? ";
			std::cin >> repeat;
			std::cout << "\n";
			repeat = toupper(repeat);

			if (repeat == 'Y' || repeat == 'N')
				break;

		}

	} while (repeat == 'Y');

	return 0;
}
Last edited on
Your function looks pretty good to me, except that I don't understand why you're passing in an argement input. Your function immediately overwrites whatever value you pass in, with the value the user inputs, so there's no need for it.

Just have input as a local variable, instead.
I'd put all of this in userPrompt():
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
		std::cout << "Player choose (R-rock, P-paper, or S-scissors)? ";
		std::cin >> userInput;
		userInput = toupper(userInput);

		while (userInput != 'R' && userInput != 'P' && userInput != 'S')
		{
			std::cout << "ERROR-1A: Must be a character from the list of 'R', 'P', or 'S'.\n";
			std::cout << "Player choose (R-rock, P-paper, or S-scissors)? ";
			std::cin >> userInput;
			userInput = toupper(userInput);

			if (userInput == 'R' || userInput == 'P' || userInput == 'S')
				break;
		}

		std::cout << "\n";


Replace lines 59-64 with computerInput = rand() % 3;

Rather than calling computerChoice() and score() inside each if/else case, just call them once after line 118.

You've made a common mistake that prevents you from greatly simplifying the if/then/else block: you read the input from the user and leave it in the user's form. So the user's selection is represented by characters 'R', 'P' and 'S' while the computer's is represented by integers 0, 1, and 2. It's better to read the user's input and then convert it to a form that's convenient for the program. When dealing with a user interface, always keep this in mind: the way you read/present the data to the user is not necessarily the best way to store it for the computer.

If you stored the values this way then lines 67-117 become:
1
2
3
4
5
6
7
if (userSelection > computerSelection || userSelection==0 && computerSelection==3) {
    win++;
} else {
    lose++;
}
computerChoice(computerInput);
score(win, lose);
@dhayden
thanks for your response!

Changes I've made:
- userInput is now 0, 1, 2
- if/else statements + another statement that includes ties.
- rand() % 3

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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#include <iostream>
#include <string>
#include <ctime>

void computerChoice(int choice)
{
	switch (choice)
	{
		case 0: std::cout << "Computer randomly played rock.\n";
			break;
		case 1: std::cout << "Computer randomly played paper.\n";
			break;
		case 2: std::cout << "Computer randomly played scissors.\n";
			break;
	}
}
void score(int WIN, int LOSE)
{
	std::cout << "User Score: " << WIN << "\nComputer Score: " << LOSE << std::endl;
}

int userPrompt(int userInput)
{
	std::cout << "----------------------------------------------\n";
	std::cout << "Player choose (0-rock, 1-paper, or 2-scissors)? ";
	std::cin >> userInput;

	while (userInput != 0 && userInput != 1 && userInput != 2)
	{
		std::cout << "ERROR-1A: Must be a number 0-2.\n";
		std::cout << "Player choose (0-rock, 1-paper, or 2-scissors)? ";
		std::cin >> userInput;

		if (userInput == 0 || userInput == 1 || userInput == 2)
			break;
	}

	std::cout << "\n";
	return userInput;
}

int main()
{
	srand(static_cast<unsigned int>(time(NULL)));
	int userInput = 0;
	int computerInput = 0;
	char repeat;

	int win = 0;
	int lose = 0;

	do
	{
		userPrompt(userInput);

		while (true)
		{
			computerInput = rand() % 3;
			if (computerInput == 0 || computerInput == 1 || computerInput == 2)
				break;
		}

		std::cout << computerInput << std::endl;

		if (userInput > computerInput || userInput == 0 && computerInput == 2)
		{
			win++;
		}
		else if (userInput < computerInput || userInput == 2 && computerInput == 0)
		{
			lose++;
		}
		else
		{
		}

		std::cout << "CompRandNum: " << computerInput << std::endl;
		computerChoice(computerInput);
		score(win, lose);

		std::cout << "\nPlay again (Y-yes || N-no)? ";
		std::cin >> repeat;
		std::cout << "\n";
		repeat = toupper(repeat);

		while (repeat != 'Y' && repeat != 'N')
		{
			std::cout << "Invalid input. Must be Y || N only.\n";
			std::cout << "Play again (Y-yes || N-no)? ";
			std::cin >> repeat;
			std::cout << "\n";
			repeat = toupper(repeat);

			if (repeat == 'Y' || repeat == 'N')
				break;

		}

	} while (repeat == 'Y');

	return 0;
}


Here's a sample output:
----------------------------------------------
Player choose (0-rock, 1-paper, or 2-scissors)? 1

ComputerRandNum: 0
Computer randomly played rock.
User Score: 0
Computer Score: 1


Last edited on
@MikeyBoy
thanks for your reply!
so, i changed the char userPrompt(char input) to int userPrompt(int userInput)
are you saying that it should just be int userPrompt() ?
are you saying that it should just be int userPrompt()

Looks like it to me. What reason would you have for passing in a value?
You still have an unnecesary look at lines 56-61. Replace it with computerInput = rand() % 3;
@MikeyBoy
hmmm... when I was rereading the book, whatever the return value is also inside the parenthesis... that's why i did it that way...?
@dhayden
so, i removed the unnecessary lines you mentioned.
I still have problems with the scoring, though

1
2
3
4
5
6
7
8
9
10
11
		if (userInput > computerInput || userInput == 0 && computerInput == 2)
		{
			win++;
		}
		else if (userInput < computerInput || userInput == 2 && computerInput == 0)
		{
			lose++;
		}
		else
		{
		}


theoretically, it should be correct.

i even did a little list thingymajig:

user, comp

win++ (userInput > computerInput || userInput == 0 && computerInput == 2)
0,2
1,0
2,1

lose++ (userInput < computerInput || userInput == 2 && computerInput == 0)
2,0
0,1
1,2

tie // i wonder if i should also create an else if statement instead of just else for tie...?
0,0
1,1
2,2



Ah, we both missed something:
win++ (userInput > computerInput || userInput == 0 && computerInput == 2)
0,2
1,0
2,1
2,0

lose++ (userInput < computerInput || userInput == 2 && computerInput == 0)
2,0
0,1
1,2
0,2

tie // i wonder if i should also create an else if statement instead of just else for tie...?
0,0
1,1
2,2

I have a feeling there's a much easier way to compute this. Maybe:
1
2
3
4
5
6
7
if (userInput == computerInput) {
    // tie
} else if (userInput == (computerInput+1)%3)
   ++win;
} else {
  ++lose;
}

Why did you add 2,0 under win++ and 0,2 under lose++?
if 2 is scissors and 0 is rock, then shouldn't that be under lose++ ...? vice versa with 0,2...

WAIT!! i get it now. 2, 0 falls under the arguments inside!!!

makes sense now!
thanks so much!!!
Topic archived. No new replies allowed.