Aaron Aaron - 2 months ago 20
C Question

unintended loop (C)

I keep getting a duplicate loop when running a Rock Paper Scissors program in C:

#include <stdio.h>
#include <stdlib.h>


int getUserInput(userInput);
int getComputerInput(cpuInput);
int pickWinner(int player, int cpu);


int main()
{

int playerWins = 0;
int compWins = 0;
int ties = 0;

int userInput;
int cpuInput;
int userChoice =1;
int compChoice;
int decision;

while (userChoice != 4)
{

compChoice = getComputerInput();
userChoice = getUserInput(userInput);

printf("computer chose %d\n", compChoice); //for debugging
printf("you chose %d \n", userChoice);//for debugging

decision = pickWinner(userChoice, compChoice);

if (decision == 1)
{
playerWins++;
}
else if (decision == 2)
{
compWins++;
}
else if (decision == 3)
{
ties++;
}


}
printf("Final score is: \nPLAYER: %d \nCOMPUTER: %d \n", playerWins, compWins);






}

//generates a random number for computer, 1=rock 2= paper 3=scissors
int getComputerInput (int cpuInput)
{

srand(time(NULL));
int r = rand() %3 +1;
return r;
}

//prompts user for character input, then converts input into a number to return back to main
int getUserInput(userInput)
{
char playerPick ;


printf("Please choose R, P, or S. (Q for quit)\n");

playerPick = getchar();



switch(playerPick)
{

case 'R' | 'r':
printf("Player chose R. \n");
return 1;
break;

case 'p':
case 'P':
printf("Player chose P. \n");
return 2;
break;

case 's':
case 'S':
printf("Player chose S. \n");
return 3;
break;

case 'q':
case 'Q':
printf("player quit");
return 4;
break;

default:
printf("Invalid choice, choose again \n");
break;

}




}
//method for determining winner
int pickWinner(int player, int cpu)
{
if (player ==1 && cpu ==1)
{
printf("tie\n\n");
return 3;

}

else if (player==1 && cpu ==2)
{
printf("you lose, paper beats rock\n\n");
return 2;
}

else if (player ==1 && cpu ==3)
{
printf("you win, rock beats scissors\n\n");
return 1;
}

else if (player ==2 && cpu ==1)
{
printf("you win, paper beats rock\n\n");
return 1;
}

else if (player ==2 && cpu ==2)
{
printf("tie\n\n");
return 3;
}
else if (player ==2 && cpu ==3)
{
printf("you lose, scissors beats paper\n\n");
return 2;
}

else if (player ==3 && cpu ==1)
{
printf("you lose, rock beats scissors\n\n");
return 2;
}

else if (player ==3 && cpu ==2)
{
printf("you win, scissors beat paper\n\n");
return 1;
}

else if (player ==3 && cpu ==3)
{
printf("tie\n\n");
return 3;
}
}


Output:

enter image description here

it seems to be passing a zero back to the getUserInput method and I cant figure out why.

any hints in the right direction would be VASTLY appreciated.

apologies if this post is not formatted correctly.

thanks in advance

Answer

When you enter input, you end the input by pressing the Enter key. That key is actually placed into the input queue as a newline.

So when you read the first character, you will get the character entered (for example 'r'). However, the next character in the input queue is the newline, and that will be what the second call to getchar will give you.

There are ways to skip that. The simplest is simply doing an extra getchar call to discard the next character. However, if that's not the newline (for example if the user entered more than one letter as input) then that will not work.

Another possible solution is to use fgets to read a whole line, and the just get the first character from that line. The problem is if you don't provide a big enough buffer to store the line, you will have the same problem as before.

The only safe solution is to read the input from the user as a character. Then in a loop read until you get the newline character. The characters you read in the loop is simply discarded.

Perhaps something like this function:

void skip_past_newline(void)
{
    int c;

    while ((c = getchar()) != '\n' && c != EOF)
    {
        // Do nothing
    }
}

Then just call it after you read the user input:

playerPick = getchar();
skip_past_newline();

Please do note a couple of things with the skip_past_newline function as presented above:

  1. The variable that receives the result of getchar is an int variable. This is actually important.

  2. I not only check for the newline in the loop, I also check for EOF. This indicates the used pressed the end-of-file key-combination (Ctrl-Z in the Windows console window) and that you should exit your program. This check is why you need to make the variable an int.