Console.KeyAvailable 为真,但 Console.In.Peek() 停止 [英] Console.KeyAvailable is true, but Console.In.Peek() stalls

查看:28
本文介绍了Console.KeyAvailable 为真,但 Console.In.Peek() 停止的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm making the game Snake. It's all working but if you press buttons too quickly it has an unfortunate behavior. Before I started attacking this issue, the code handled a single key press per loop iteration, and if you pressed a key multiple times in a row, it took that many loops before you could change direction.

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

My initial change was to read all the keys that have been pressed since the last game loop, and only apply the last one. This worked, but really, if I press two keys, I want them both to be applied. What I don't want is for me to be stuck going right because I pressed right three times.

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

So my next approach was to peek at the next inputted character and see if it's the same as the last one. If so, read it out of the stream, and try again.

我的理解是Console.KeyAvailable在输入流中有任何未读数据时返回true,并且Console.In.Peek()code> 返回输入流中数据的第一个字符,否则挂起直到那里有数据.

My understanding is that Console.KeyAvailable returns true if there is any unread data in the input stream, and Console.In.Peek() returns the first character of data in the input stream, or else hangs until there is data there.

这是我当前的代码:

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(); 并等待下一个字符.

If I press two keys on the same loop, the game stalls. What happens (as far as I can tell) is it gets to int next = Console.In.Peek(); and waits for the next character.

我不明白的是为什么 Console.In.Peek() 需要等待.如果 Console.KeyAvailable 为真,则 Console.In 的流中应该有一个字符.

What I don't understand is why Console.In.Peek() needs to wait. If Console.KeyAvailable is true, then there should be a character in Console.In's stream.

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

I believe I've figured out the issue. Console.In.Peek() is looking for characters, not key presses, and the arrow buttons don't have characters associated with them. So my next question is how to do what I want to do.

推荐答案

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

I also made a snake multiplayer game (source code here) and i had exact the same poblem: If somebody presses a key for a while then the direction is set very delayed...

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

I solved this problem with a keyBuffer and a keyCheck thread:

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
}

这篇关于Console.KeyAvailable 为真,但 Console.In.Peek() 停止的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆