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

时间:2015-01-04 00:41:54

标签: c# stream

我正在制作游戏Snake。这一切都有效,但是如果你按下按钮太快就会发生不幸的行为。在我开始攻击此问题之前,代码在每次循环迭代时处理了一次按键操作,如果您连续多次按下某个键,则在更改方向之前需要进行多次循环。

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

所以我的下一个方法是偷看下一个输入的角色,看看它是否与最后一个相同。如果是这样,请从流中读出,然后重试。

我的理解是Console.KeyAvailable如果输入流中有任何未读数据,则返回trueConsole.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为真,则Console.In的流中应该有一个字符。

修改

我相信我已经弄明白了这个问题。 Console.In.Peek()正在寻找字符,而不是按键,箭头按钮没有与之关联的字符。所以我的下一个问题是如何做我想做的事。

2 个答案:

答案 0 :(得分:3)

没有使用Console.ReadKey()的可能性。你只对控制蛇的键的位置感兴趣,而不是它们产生的字母。例如,WASD是ZQSD in France。并且您可以使用光标键,而不能使用Console.Read()

答案 1 :(得分:2)

我还做了一个蛇多人游戏(源代码here),我有完全相同的问题: 如果有人按下键一段时间,那么方向设置得非常延迟......

我用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
}