这为什么会挂断?菜单程序

时间:2015-11-19 21:11:54

标签: c#

class menu
{
    string[] elements;
    public menu(string[] ele) { elements = ele; }
    public menu() : this(new string[3]) { }
    public void dispMenu(int sel)
    {
        Console.Clear();
        Console.SetCursorPosition(0, 0);
        for (int i = 0; i != elements.Length; i++)
        {
            if (i != sel) { Console.WriteLine(" " + elements[i]); }
            else { Console.WriteLine(">" + elements[i] + "<"); }                
        }
    }
    public int doMenu()
    {
        int selection = 0;
        do
        {
            dispMenu(selection);
            while (!Console.KeyAvailable)
            {

            }
            if (Console.ReadKey().Key == ConsoleKey.UpArrow)
            {
                if (selection == 0) { selection = elements.Length; }
                else { selection--; }
            }
            else if (Console.ReadKey().Key == ConsoleKey.DownArrow)
            {
                if (selection == elements.Length) { selection = 0; }
                else { selection++; }
            }
        } while (Console.ReadKey(true).Key != ConsoleKey.Enter);
        return selection;
    }
}
class Program
{
    static void Main(string[] args)
    {
        menu swag = new menu(new string[3] {"Swag", "Money", "yolo"});
        Console.WriteLine(swag.doMenu());
        Console.Read();
    }
}

为什么会挂断?它是一个菜单对象,它应该响应向上和向下箭头,并在按下enter时终止,返回选择。在运行时它可以工作,但是你必须按几次键才能让它注册。 enter键也表现为这种方式。

3 个答案:

答案 0 :(得分:1)

在进行所有比较之前,将Console.ReadKey()结果分配给变量一次。否则我相信它会在每次遇到条件时尝试读取输入。现在你做了三次,所以第一次按键时它只会比较UpArrow的条件,第二次 - 对于DownArrow,第三次 - 仅对于Enter,所以你必须按几次键才能处理。 你的doMenu方法有类似的东西:

public int doMenu()
{
    int selection = 0;
    ConsoleKeyInfo consoleKeyInfo;
    do
    {
        dispMenu(selection);
        while (!Console.KeyAvailable)
        {

        }
        consoleKeyInfo = Console.ReadKey();
        if (consoleKeyInfo.Key == ConsoleKey.UpArrow)
        {
            if (selection == 0) { selection = elements.Length; }
            else { selection--; }
        }
        else if (consoleKeyInfo.Key == ConsoleKey.DownArrow)
        {
            if (selection == elements.Length) { selection = 0; }
            else { selection++; }
        }
    } while (consoleKeyInfo.Key != ConsoleKey.Enter);
    return selection;
}

答案 1 :(得分:1)

Console.ReadKey()方法返回用户按下的下一个字符或功能键。您在循环中多次调用此方法,因此第一个调用读取第一个键,第二个调用读取第二个键,依此类推。除非您在正确的时刻点击正确的密钥,否则您的代码无法正常工作。

documentation states

  

ReadKey方法等待,即发出ReadKey方法的线程上的块,直到按下字符或功能键

所以检查空!Console.KeyAvailable的循环是不必要的。

代码可以简化如下

public int doMenu() {
    int selection = 0;
    ConsoleKeyInfo key = null;

    do {
        dispMenu(selection);
        key = Console.ReadKey();

        if (key.Key == ConsoleKey.UpArrow)
        {
            if (selection == 0) { selection = elements.Length; }
            else { selection--; }
        }
        else if (key.Key == ConsoleKey.DownArrow)
        {
            if (selection == elements.Length) { selection = 0; }
            else { selection++; }
        }
    } while (key.Key != ConsoleKey.Enter);
    return selection;
}

答案 2 :(得分:0)

就像Console.ReadLine()函数一样,每次出现函数时,它都会暂停程序以接收输入。正如raderick所说,你应该将ReadKey分配给一个变量,所以它只要求输入一次。