Reputation: 19
While loop iterates two times every time, and CPU only scores point when choosing 'S' for scissors. Another question is, how do I make it toupper and where do I add that function? I have to use characters 'r','s', and 'p', instead of 1,2,3 to accept user input. Not sure how to proceed to fix this
#include <stdlib.h>
#include<time.h>
int main () {
char player1;
int player2;
int userScore = 0, cpuScore = 0;
player2 = rand ( ) % 3 + 1;
srand ((int) time (NULL));
int count = 0;
while(count <= 10) {
printf("\nEnter p for Paper, r for rock, or S for scissor: ");
scanf("%c", &player1);
switch(player1) {
case 'P' :
if(player1 == 'P' && player2 == 1) {
printf("Draw!");
break;
} else if(player1 == 'P' && player2 == 2) {
userScore++;
printf("User won this one!");
break;
} else {
cpuScore++;
printf("CPU won this one!");
break;
}
case 'R':
if(player1 == 'R' && player2 == 2) {
printf("Draw!");
break;
} else if(player1 == 'R' && player2 == 3) {
userScore++;
printf("User won this one!");
break;
} else {
cpuScore++;
printf("CPU won this one!");
break;
}
case 'S':
if(player1 == 'S' && player2 == 3) {
printf("Draw!");
break;
} else if(player1 == 'S' && player2 == 1) {
userScore++;
break;
printf("User won this one!");
} else {
cpuScore++;
printf("CPU won this one!");
break;
}
default :
printf("\nInvalid Input");
break;
}
printf("\nUser Score: %d", userScore);
printf("\nCPU Score: %d", cpuScore);
count++;
}
if(userScore == cpuScore) {
printf("\nDraw game!");
} else if(userScore > cpuScore) {
printf("\nYou win!");
} else {
printf("\nCPU wins!");
}
return 0;
} ```
Upvotes: 0
Views: 240
Reputation: 93524
I suggest you fix it by making it far less complicated. The winner of Rock-Paper-Scissors can be determined arithmetically.
It is simpler to compare like for like, and using integer values allows a simpler arithmetic solution. Also arithmetically it is simpler to use 0,1,2 rather than 1,2,3. So first transform the user input to 0,1,2:
#define INVALID_SELECTION sizeof(rps)
static const char rps[] = {'r', 'p', 's'} ;
int human = INVALID_SELECTION ;
while( human == INVALID_SELECTION )
{
printf("\nEnter R for Rock, P for Paper, or S for Scissors: ");
char ch = 0 ;
scanf("%c", &ch ) ;
while( ch != '\n' && getchar() != '\n' ) ;
for( human = 0;
human < INVALID_SELECTION && tolower(ch) != rps[human] ;
human++ )
{
// do nothing
}
}
The computer play should then be determined thus :
srand( (int)time(NULL) ) ;
int computer = rand() % 3 ;
though note that you need only call srand()
once, so if you put the game in a loop to repeat play, the srand()
call should appear before the repeat loop.
You can then report the play thus:
static const char* play_lookup[] = { "Rock", "Paper", "Scissors" } ;
printf( "Human played %s\n", play_lookup[human] ) ;
printf( "Computer played %s\n", play_lookup[computer] ) ;
Then human
and computer
are directly and arithmetically comparable such that:
int battle = human - computer ;
if( battle < 0 ) battle += 3 ;
switch( battle )
{
case 0 : printf( "Draw!\n" ) ; break ;
case 1 : printf( "Human wins!\n" ) ; break ;
case 2 : printf( "Computer wins!\n" ) ; break ;
}
or (credit to @HAL9000):
int battle = ((human - computer) + 3) % 3 ;
switch( battle )
...
Putting it all together:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <time.h>
int main()
{
// Randomize
srand( (int)time(NULL) ) ;
// Repeat play indefinitely
for(;;)
{
#define INVALID_SELECTION sizeof(rps)
static const char rps[] = {'r', 'p', 's'} ;
int human = INVALID_SELECTION ;
// While human input is not one of R,P,S,r,p or s...
while( human == INVALID_SELECTION )
{
printf("\nEnter R for Rock, P for Paper, or S for Scissors: ");
char ch = 0 ;
scanf("%c", &ch ) ;
while( ch != '\n' && getchar() != '\n' ) ;
// Transform input to one of 0,1,2 (for R,P,S respectively)
for( human = 0;
human < INVALID_SELECTION && tolower(ch) != rps[human] ;
human++ )
{
// do nothing
}
}
// Get computer's play
int computer = rand() % 3 ;
// Report human and computer plays in full text
static const char* play_lookup[] = { "Rock", "Paper", "Scissors" } ;
printf( "Human played %s\n", play_lookup[human] ) ;
printf( "Computer played %s\n", play_lookup[computer] ) ;
// Calculate and report result
int battle = ((human - computer) + 3) % 3 ;
switch( battle )
{
case 0 : printf( "Draw!\n" ) ; break ;
case 1 : printf( "Human wins!\n" ) ; break ;
case 2 : printf( "Computer wins!\n" ) ; break ;
}
}
return 0;
}
Example output:
Enter R for Rock, P for Paper, or S for Scissors: r
Human played Rock
Computer played Rock
Draw!
Enter R for Rock, P for Paper, or S for Scissors: r
Human played Rock
Computer played Scissors
Human wins!
Enter R for Rock, P for Paper, or S for Scissors: r
Human played Rock
Computer played Rock
Draw!
Enter R for Rock, P for Paper, or S for Scissors: r
Human played Rock
Computer played Scissors
Human wins!
Enter R for Rock, P for Paper, or S for Scissors: r
Human played Rock
Computer played Paper
Computer wins!
Enter R for Rock, P for Paper, or S for Scissors: p
Human played Paper
Computer played Paper
Draw!
Enter R for Rock, P for Paper, or S for Scissors: p
Human played Paper
Computer played Scissors
Computer wins!
Enter R for Rock, P for Paper, or S for Scissors: p
Human played Paper
Computer played Rock
Human wins!
Enter R for Rock, P for Paper, or S for Scissors: s
Human played Scissors
Computer played Scissors
Draw!
Enter R for Rock, P for Paper, or S for Scissors: s
Human played Scissors
Computer played Paper
Human wins!
Enter R for Rock, P for Paper, or S for Scissors: s
Human played Scissors
Computer played Paper
Human wins!
Enter R for Rock, P for Paper, or S for Scissors: s
Human played Scissors
Computer played Scissors
Draw!
Enter R for Rock, P for Paper, or S for Scissors: s
Human played Scissors
Computer played Rock
Computer wins!
Enter R for Rock, P for Paper, or S for Scissors: R
Human played Rock
Computer played Scissors
Human wins!
Enter R for Rock, P for Paper, or S for Scissors: P
Human played Paper
Computer played Paper
Draw!
Enter R for Rock, P for Paper, or S for Scissors: S
Human played Scissors
Computer played Paper
Human wins!
Enter R for Rock, P for Paper, or S for Scissors: xx
Enter R for Rock, P for Paper, or S for Scissors: yy
Enter R for Rock, P for Paper, or S for Scissors: zz
Enter R for Rock, P for Paper, or S for Scissors:
Upvotes: 3
Reputation: 1922
The problem is you are setting player2
outside the loop, and not updating it; it will constantly be the same. Instead of converting it to an intermediary value by toupper
, this is probably a typical case where converting it directly to an enum
would be appropriate. Instead of a switch
with if
, this shrinks your problem space to 3 values, which fits in a lookup-table easily.
#include <stdlib.h>
#include <stdio.h> /* `printf` requires this. */
#include <time.h>
/* https://en.wikipedia.org/wiki/X_Macro just because I don't want to type. */
#define CHOICE(X) X(ROCK), X(PAPER), X(SCISSORS)
#define OUTCOME(X) X(LOSS), X(TIE), X(WIN)
#define NAME(A) A
#define STR(A) #A
enum Choice { CHOICE(NAME) };
static const char *const choice_names[] = { CHOICE(STR) };
enum Outcome { OUTCOME(NAME) };
static const char *const outcome_names[] = { OUTCOME(STR) };
static enum Outcome choice_outcomes[][3] = {
{ TIE, LOSS, WIN },
{ WIN, TIE, LOSS },
{ LOSS, WIN, TIE }
};
int main(void) { /* <- `void` should be used to prototype. */
char input;
enum Choice player1, player2;
int score[] = { 0, 0, 0 }; /* <- Replace `cpuScore` and `userScore`. */
int count = 0;
srand ((int) time (NULL)); /* <- `srand` should precede `rand`. */
while(count <= 10) {
printf("\nEnter p for Paper, r for rock, or S for scissor: ");
/* Ignores whitespace, (_viz_ enter); breaks on error, (_eg_ EOF.) */
if(scanf(" %c", &input) != 1) break;
/* Convert it to `player1` immediately. */
switch(input) {
case 'r': case 'R':
player1 = ROCK; break;
case 'p': case 'P':
player1 = PAPER; break;
case 's': case 'S':
player1 = SCISSORS; break;
default:
printf("Unexpected input, '%c'.\n", input); continue;
}
player2 = rand() % 3;
printf("User choses %s _vs_ Cpu choses %s: %s.\n",
choice_names[player1], choice_names[player2],
outcome_names[choice_outcomes[player1][player2]]);
score[choice_outcomes[player1][player2]]++;
printf("User Score: %d\n", score[WIN]);
printf("CPU Score: %d\n", score[LOSS]);
printf("Ties: %d\n", score[TIE]);
count++;
}
/* One of the places was the `scanf` break, so check, (unlikely.) */
if(ferror(stdin)) { perror("stdin"); return 1; }
/* Print the winner. */
if(score[WIN] == score[LOSS]) {
printf("Draw game!\n");
} else if(score[WIN] > score[LOSS]) {
printf("You win!\n");
} else {
printf("CPU wins!\n");
}
return 0;
}
I also put userScore
and cpuScore
into an array indexed by enum Outcome
.
Upvotes: 0
Reputation: 81
Try this:
#include <stdio.h>
#include <stdlib.h>
int main () {
char player1;
int player2;
int userScore = 0, cpuScore = 0;
srand ((int) time (NULL));
int count = 0;
while(count != 10) {
printf("Enter p for Paper, r for rock, or S for scissor:\n");
fgets(&player1, 80, stdin);
player2 = rand ( ) % 4;
if(player1 == 'P' && player2 == 1) {
printf("Draw!\n");
}if(player1 == 'P' && player2 == 2) {
userScore++;
printf("User won this one!\n");
}if(player1 == 'P' && player2 == 3){
cpuScore++;
printf("CPU won this one!\n");
}
if(player1 == 'R' && player2 == 2) {
printf("Draw!\n");
}if(player1 == 'R' && player2 == 3) {
userScore++;
printf("User won this one!\n");
}if(player1 == 'R' && player2 == 1){
cpuScore++;
printf("CPU won this one!\n");
}
if(player1 == 'S' && player2 == 3) {
printf("Draw!\n");
}if(player1 == 'S' && player2 == 1) {
userScore++;
printf("User won this one!\n");
}if(player1 == 'S' && player2 == 2){
cpuScore++;
printf("CPU won this one!\n");
}
if(player1!='S' || player1!='R' || player1!='P'){
printf("Invalid Input\n");
}
printf("User Score: %d\n", userScore);
printf("CPU Score: %d\n", cpuScore);
count++;
}
if(userScore == cpuScore) {
printf("Draw game!\n");
} else if(userScore > cpuScore) {
printf("You win!\n");
} else {
printf("CPU wins!\n");
}
return 0;
}
I should also add that this program is sensitive. For example, inputting 'r' will not work but 'R' will. Change this at your discretion.
Upvotes: 1