我正在尝试开发一个简单的基于文本的刽子手游戏,并且主游戏循环以提示输入每个字母的猜测开始,然后继续检查字母是否在单词中并且如果它生命关闭不是.但是,当我运行游戏时,每次提示两次,程序不会等待用户的输入.它也会夺去生命(如果它是正确的输入就会有一个生命,如果没有,则为两个生命),所以无论它采取的是什么都与之前的输入不同.这是我的游戏循环,简化了一下:
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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
我认为问题是scanf认为它没有,但我不明白为什么.有谁有想法吗?我在Mac OS X 10.5上使用gcc 4.0.1.
bta*_*bta 21
当您读取键盘输入时scanf(),按下输入后读取输入,但输入键生成的换行不会被调用消耗scanf().这意味着下次你从标准输入读取时会有一个等待你的换行符(这将使下一个scanf()呼叫立即返回而没有数据).
为避免这种情况,您可以将代码修改为:
scanf("%c%*c", ¤tGuess);
Run Code Online (Sandbox Code Playgroud)
该%*c匹配单个字符,但星号表示该角色会不会被存储在任何地方.这会产生消耗enter键生成的换行符的效果,这样下次调用时scanf()就会以空输入缓冲区开始.
警告: 如果用户按下两个键然后按Enter键,scanf()将返回第一个击键,吃第二个键,然后保留换行符以进行下一个输入调用.像这样的怪癖是scanf()许多程序员避免和朋友避开的原因之一.
第一次通过循环,scanf()读取字符.然后它读取换行符.然后它读取下一个字符; 重复.
我很少使用scanf(),但是如果你使用格式字符串"%.1s",它应该跳过空格(包括换行符),然后读取非空格字符.但是,它将期待一个字符数组而不是一个字符:
char ibuff[2];
while ((scanf("%.1s", ibuff) == 1)
{
...
}
Run Code Online (Sandbox Code Playgroud)
将问题分解为更小的部分:
int main(void) {
char val;
while (1) {
printf("enter val: ");
scanf("%c", &val);
printf("got: %d\n", val);
}
}
Run Code Online (Sandbox Code Playgroud)
这里的输出是:
enter val: g
got: 103
enter val: got: 10
Run Code Online (Sandbox Code Playgroud)
为什么scanf会给你另外一个'10'?
由于我们为我们的值打印了ASCII码,因此ASCII中的'10'是"enter",因此scanf还必须将"enter"键作为一个字符.
果然,看着你的scanf字符串,你每次循环都要求一个字符.控制字符也被视为字符,将被拾取.例如,您可以在上面的循环中按"esc"然后"enter"并获取:
enter val: ^[
got: 27
enter val: got: 10
Run Code Online (Sandbox Code Playgroud)