我正在尝试开发一个简单的基于文本的刽子手游戏,主游戏循环从提示输入每个字母的猜测开始,然后继续检查该字母是否在单词中,如果出现则夺走生命。不是。但是,当我运行游戏时,每次都会出现两次提示,并且程序不会等待用户的输入。它还会夺走一条生命(如果输入正确,则一条生命,如果不正确,则两条生命),因此无论它吸收什么,都与之前的输入不同。这是我的游戏循环,稍微简化了一些:

while (!finished)
{
    printf("Guess the word '%s'\n",covered);

    scanf("%c", &currentGuess);

    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。

有帮助吗?

解决方案

当您阅读scanf()键盘输入,输入之后读取输入按下而是由输入密钥生成的新行不会被调用scanf()消耗。这意味着你从标准输入读取下一次会有等着你(这将使没有数据的下一scanf()呼叫立即返回)一个换行符。

要避免这种情况,你可以修改你的代码是这样的:

scanf("%c%*c", &currentGuess);

%*c匹配单个字符,但星号表示该字符将不被存储在任何地方。这具有通过消耗输入键产生的换行字符,使得下一次调用scanf()你开始使用空输入缓冲器的效果。

<强>警告:如果用户按下两个键,然后按下回车,scanf()将返回第一次击键,吃第二和离开换行的下一个输入呼叫。像这样的怪癖是原因之一scanf()和朋友被许多程序员避免。

其他提示

换行。

在第一次循环时,scanf()的读出的字符。 然后,它读取换行符。 然后,它读取下一个字符;重复。

如何解决?

我很少用scanf()的,但是如果使用的格式串"%.1s",应该跳过白色空间(包括换行),然后读出的非空白字符。然而,将被期望的字符阵列而不是单个字符:

char ibuff[2];

while ((scanf("%.1s", ibuff) == 1)
{
    ...
}

打破问题成更小的部分:

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数字,“10”在ASCII是“输入”,所以scanf还必须抓住“输入”键作为一个字符。

果然,看着你scanf字符串,你通过你的循环每次都询问一个字符。控制字符也被视为字符,并会有所回升。例如,可以按“ESC”那么在上述循环“输入”,并得到:

enter val: ^[
got: 27
enter val: got: 10

只是一个猜测,但你输入与scanf的单个字符,但用户必须键入猜测加一个新行,其被消耗作为一个单独的猜测字符。

scanf(" %c", &fooBar);

注意%c之前的空间。这是重要的,因为它前面的所有空白匹配。

吉姆和Jonathan有它的权利。

要得到你的scanf线做你想要的(消费换行符的W / O把它在缓存),我将其更改为

scanf("%c\n", &currentGuess);

(注意\n

处理在这个错误是恶劣虽然。在至少应检查从scanf的返回值对1,而忽视了输入(具有警告),如果它不返回。

我注意到几点:

  • scanf("%c") 将读取 1 个字符并将 ENTER 保留在输入缓冲区中以供下次循环使用
  • 你正在增加 i 即使从用户读取的字符与中的字符不匹配 secretWord
  • 什么时候 covered[j] 曾经成为“-”吗?

我想:你的代码是处理一个换行符,当您输入数据的猜测之一。我一直回避* scanf()系列,由于无法控制的错误处理。尝试使用与fgets()代替,然后拉出第一个字符/字节。

我在您的代码中看到了一些内容:

  1. scanf 返回它读取的项目数。您可能需要处理返回 0 或 EOF 的情况。
  2. 我的猜测是用户按下字母 + Enter 并且您将换行符作为第二个字符。一种简单的检查方法是添加调试 printf 语句以显示输入的字符。
  3. 您的代码将仅匹配匹配字母的第一次出现,即如果单词是“test”并且用户输入“t”,则您的代码将仅匹配第一个“t”,而不是两者。您需要调整第一个循环来处理这个问题。

当你输入的字符,你必须输入一个空格字符继续前进。此空白字符是存在于输入缓冲器,stdin文件,并且由scanf()功能读取。 这个问题可以通过这种消耗多余的字符来解决。这可以通过一个usnig功能getchar()来完成。

scanf("%c",&currentGuess);  
getchar();   // To consume the whitespace character.

我宁愿建议你避免使用scanf(),而使用getchar()。该scanf()requires大量的内存空间。 getchar()是一个光功能。所以,你也可以使用 -

char currentGuess;  
currentGuess=getchar();  
getchar();  // To consume the whitespace character.
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top