Console.KeyAvailable 为 true,但 Console.In.Peek() 停止

问题描述 投票:0回答:2

我正在制作贪吃蛇游戏。这一切都正常,但如果你按下按钮太快,就会出现不幸的行为。在我开始解决这个问题之前,代码每次循环迭代处理一次按键,如果您连续多次按下一个键,则需要多次循环才能改变方向。

我最初的更改是读取自上次游戏循环以来按下的所有键,并且仅应用最后一个。这有效,但实际上,如果我按两个键,我希望它们都被应用。我不想要的是因为我按了三次右键而被困在右方向。

所以我的下一个方法是查看下一个输入的字符,看看它是否与上一个相同。如果是这样,请从流中读取它,然后重试。

我的理解是,如果输入流中有任何未读数据,

Console.KeyAvailable
返回
true
Console.In.Peek()
返回输入流中数据的第一个字符,否则挂起,直到有数据为止。

这是我当前的代码:

private static void UpdateDirection()
{
    ConsoleKey key = ConsoleKey.Escape; // dummy key

    Dir curDir = s_snakeDir;
    lock (s_consoleLock)
    {
        if (Console.KeyAvailable)
        {
            key = Console.ReadKey(true).Key;

            // ignore multiple key presses of the same direction
            while (Console.KeyAvailable)
            {
                int next = Console.In.Peek();
                if (next != (int)key)
                {
                    break;
                }

                // read and ignore next character
                Console.ReadKey(true);
            }
        }

        switch (key)
        {
            // do stuff...
        }
    }
}

如果我在同一个循环中按两个键,游戏就会停止。发生的情况(据我所知)是到达

int next = Console.In.Peek();
并等待下一个字符。

我不明白的是为什么

Console.In.Peek()
需要等待。如果
Console.KeyAvailable
为 true,那么
Console.In
的流中应该有一个字符。

编辑

我相信我已经解决了这个问题。

Console.In.Peek()
正在寻找字符,而不是按键,并且箭头按钮没有与之关联的字符。所以我的下一个问题是如何做我想做的事。

c# stream
2个回答
4
投票

我还制作了一个贪吃蛇多人游戏(源代码这里),我也遇到了完全同样的问题: 如果有人按下某个键一段时间,那么方向就会设置得非常延迟......

我用 keyBuffer 和 keyCheck 线程解决了这个问题:

List<ConsoleKeyInfo> keyBuffer = new List<ConsoleKeyInfo>();

new Thread(() =>
{
    while(true)
    {
        if (Console.KeyAvailable)
        {
            ConsoleKeyInfo key = Console.ReadKey(true);
            if (keyBuffer.Count > 0)
            {
                if (keyBuffer[keyBuffer.Count - 1] != key)
                    keyBuffer.Add(key);
            }
            else
                keyBuffer.Add(key);
        }
        Thread.Sleep(1);
    }
}).Start();

while(true)
{
    if (keyBuffer.Count>0)
    {
        switch (keyBuffer[0].Key)
        {
            //SwitchSomeStuff
        }
        keyBuffer.RemoveAt(0);
    }
    //PlayGame
}

3
投票

不使用 Console.ReadKey() 是没有道理的。您只对控制蛇的按键位置感兴趣,而不对它们产生的字母感兴趣。例如,WASD 在法国是 ZQSD:

并且您可以使用光标键,但不能使用 Console.Read() 来做到这一点

© www.soinside.com 2019 - 2024. All rights reserved.