我正在尝试开发一个简单的基于文本的刽子手游戏,并且主游戏循环以提示输入每个字母的猜测开始,然后继续检查字母是否在单词中并且需要生命如果不是。但是,当我运行游戏时,每次提示两次,程序不会等待用户的输入。它也会夺去生命(如果它是正确的输入,则为一生,如果不是,则为两个生命),因此无论它采取的是什么都与之前的输入不同。这是我的游戏循环,简化了一下:
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;
}
}
}
我认为问题是scanf认为当它没有时会采取一些措施,但我不知道为什么。有谁有想法吗?我在Mac OS X 10.5上使用gcc 4.0.1。
答案 0 :(得分:19)
当您使用scanf()
读取键盘输入时,按下输入后会读取输入,但输入键生成的换行不会被scanf()
的调用消耗。这意味着下次您从标准输入读取时会有一个等待您的换行符(这会使下一个scanf()
调用立即返回而没有数据)。
为避免这种情况,您可以将代码修改为:
scanf("%c%*c", ¤tGuess);
%*c
匹配单个字符,但星号表示该字符不会存储在任何位置。这会消耗enter键生成的换行符,以便下次调用scanf()
时,您将以空输入缓冲区开始。
警告:如果用户按下两个键然后按Enter键,scanf()
将返回第一次击键,吃第二次,然后保留换行符以进行下一次输入调用。像这样的怪癖是许多程序员避免scanf()
和朋友的原因之一。
答案 1 :(得分:8)
第一次循环,scanf()读取字符。 然后它读取换行符。 然后它读取下一个字符;重复。
我很少使用scanf(),但是如果你使用格式字符串"%.1s"
,它应该跳过空格(包括换行符),然后读取非空格字符。但是,它会期望一个字符数组而不是一个字符:
char ibuff[2];
while ((scanf("%.1s", ibuff) == 1)
{
...
}
答案 2 :(得分:5)
将问题分解为更小的部分:
int main(void) {
char val;
while (1) {
printf("enter val: ");
scanf("%c", &val);
printf("got: %d\n", val);
}
}
这里的输出是:
enter val: g
got: 103
enter val: got: 10
为什么scanf
会给你另外一个'10'?
由于我们为我们的值打印了ASCII码,因此ASCII中的“10”为“enter”,因此scanf
也必须将“输入”键作为字符抓取。
果然,看着你的scanf
字符串,每次循环都会要求一个字符。控制字符也被视为字符,将被拾取。例如,您可以在上面的循环中按“esc”然后“enter”并获取:
enter val: ^[
got: 27
enter val: got: 10
答案 3 :(得分:3)
只是一个猜测,但是您输入的是一个带有scanf的单个字符,但是用户必须输入猜测加上换行符,换行符将作为单独的猜测字符使用。
答案 4 :(得分:3)
scanf(" %c", &fooBar);
注意%c
之前的空格。这很重要,因为它匹配所有前面的空格。
答案 5 :(得分:2)
吉姆和乔纳森做得对。
让你的scanf行做你想做的事情(使用换行符而不把它放在缓冲区中)我将它改为
scanf("%c\n", ¤tGuess);
(请注意\n
)
但是对此的错误处理是非常糟糕的。至少你应该检查scanf的返回值是否为1,如果没有返回,则忽略输入(带警告)。
答案 6 :(得分:1)
我注意到几点:
scanf("%c")
将读取1个字符并将ENTER保留在输入缓冲区中以供下次循环使用i
secretWord
covered[j]
何时成为' - '?答案 7 :(得分:1)
我猜:当你输入数据时,你的代码将换行视为猜测之一。由于无法控制的错误处理,我总是避免使用* scanf()系列。尝试使用fgets()代替,然后拔出第一个字符/字节。
答案 8 :(得分:0)
我在你的代码中看到了一些东西:
答案 9 :(得分:0)
输入字符时,必须输入空白字符才能继续。此空白字符存在于输入缓冲区stdin
文件中,由scanf()
函数读取。
消耗这个额外的角色可以解决这个问题。这可以通过使用getchar()
函数来完成。
scanf("%c",¤tGuess);
getchar(); // To consume the whitespace character.
我建议您避免使用scanf()
,而是使用getchar()
。 scanf()
需要大量内存空间。 getchar()
是一项轻量级功能。所以你也可以使用 -
char currentGuess;
currentGuess=getchar();
getchar(); // To consume the whitespace character.