I'm trying to develop a simple text-based hangman game, and the main game loop starts with a prompt to enter a guess at each letter, then goes on to check if the letter is in the word and takes a life off if it isn't. However, when I run the game the prompt comes up twice each time, and the program doesn't wait for the user's input. It also takes off a life (one life if it was the right input, two if it wasn't), so whatever it's taking in isn't the same as the previous input. Here's my game loop, simplified a bit:
while (!finished)
{
printf("Guess the word '%s'\n",covered);
scanf("%c", ¤tGuess);
i=0;
while (i<=wordLength)
{
if (i == wordLength)
{
--numLives;
printf("Number of lives: %i\n", numLives);
break;
} else if (currentGuess == secretWord[i]) {
covered[i] = secretWord[i];
secretWord[i] = '*';
break;
}
++i;
}
j=0;
while (j<=wordLength)
{
if (j == (wordLength)) {
finished = 1;
printf("Congratulations! You guessed the word!\n");
break;
} else {
if (covered[j] == '-') {
break;
}
}
++j;
if (numLives == 0) {
finished = 1;
}
}
}
I assume the problem is scanf thinking it's taken something in when it hasn't, but I have no idea why. Does anyone have any idea? I'm using gcc 4.0.1 on Mac OS X 10.5.
I see a couple of things in your code:
When you enter the character, you have to enter a whitespace character to move on. This whitespace character is present in the input buffer,
stdin
file, and is read by thescanf()
function. This problem can be solved by consuming this extra character. This can be done by usnig agetchar()
function.I would rather suggest you to avoid using
scanf()
and instead usegetchar()
. Thescanf()
requires a lot of memory space.getchar()
is a light function. So you can also use-When you read keyboard input with
scanf()
, the input is read after enter is pressed but the newline generated by the enter key is not consumed by the call toscanf()
. That means the next time you read from standard input there will be a newline waiting for you (which will make the nextscanf()
call return instantly with no data).To avoid this, you can modify your code to something like:
The
%*c
matches a single character, but the asterisk indicates that the character will not be stored anywhere. This has the effect of consuming the newline character generated by the enter key so that the next time you callscanf()
you are starting with an empty input buffer.Caveat: If the user presses two keys and then presses enter,
scanf()
will return the first keystroke, eat the second, and leave the newline for the next input call. Quirks like this are one reason whyscanf()
and friends are avoided by many programmers.I'll guess: your code is treating a newline as one of the guesses when you enter data. I've always avoided the *scanf() family due to uncontrollable error handling. Try using fgets() instead, then pulling out the first char/byte.
Newlines.
The first time through the loop, scanf() reads the character. Then it reads the newline. Then it reads the next character; repeat.
How to fix?
I seldom use scanf(), but if you use a format string
"%.1s"
, it should skip white space (including newlines) and then read a non-white space character. However, it will be expecting a character array rather than a single character:A couple points I noticed:
scanf("%c")
will read 1 character and keep the ENTER in the input buffer for next time through the loopi
even when the character read from the user doesn't match the character insecretWord
covered[j]
ever get to be '-'?