C# 根据用户击键更改控制台上的字符

C# 根据用户击键更改控制台上的字符,c#,console,C#,Console,我想做的是根据用户按下的按钮更改控制台 我有一个控制台,有三个选项,如下所示: > Option 1 Option 2 Option 3 Option 1 > Option 2 Option 3 基本上,如果用户按下向下箭头,控制台将如下所示: > Option 1 Option 2 Option 3 Option 1 > Option 2 Option 3 如果用户按下向上箭头,控制台将返回初始状态 我知道如何使用Console.Read

我想做的是根据用户按下的按钮更改控制台

我有一个控制台,有三个选项,如下所示:

>  Option 1

Option 2

Option 3
Option 1

>  Option 2

Option 3
基本上,如果用户按下向下箭头,控制台将如下所示:

>  Option 1

Option 2

Option 3
Option 1

>  Option 2

Option 3
如果用户按下向上箭头,控制台将返回初始状态

我知道如何使用Console.ReadKey()读取用户的输入,但我不知道如何修改已经写入的输出


最后一件事是,当用户按enter键时,控制台不会创建新行,而是选择其中一个选项并调用一个代理。

使用
console.ReadKey
和一些变量来保存所选选项的状态,这并不难实现

下面的代码是一个非常快速和懒惰的实现,它实现了您正在寻找的内容。花点时间自己适当地重写它——这是为了让你知道如何实现你想要的

static void Main(string[] args)
{
    bool IsRunning = true;
    int Selected = 1;

    while (IsRunning)
    {
        ConsoleKeyInfo NextKey = new ConsoleKeyInfo();

        if (Selected < 1)
            Selected = 3;
        else if (Selected > 3)
            Selected = 1;

        Console.Clear();
        if (Selected == 1)
            Console.Write("> ");
        Console.WriteLine("Option 1");
        Console.WriteLine();
        if (Selected == 2)
            Console.Write("> ");
        Console.WriteLine("Option 2");
        Console.WriteLine();
        if (Selected == 3)
            Console.Write("> ");
        Console.WriteLine("Option 3");
        Console.WriteLine();
        Console.Write("Choose an option (Q to Quit): ");

        while (!(NextKey.Key == ConsoleKey.DownArrow ||
                NextKey.Key == ConsoleKey.UpArrow ||
                NextKey.Key == ConsoleKey.Q ||
                (NextKey.KeyChar >= '1' &&
                NextKey.KeyChar <= '3')))
        {
            NextKey = Console.ReadKey();
        }

        switch (NextKey.Key)
        {
            case ConsoleKey.D1:
                // Do something
                break;

            case ConsoleKey.D2:
                // Do something
                break;

            case ConsoleKey.D3:
                // Do something
                break;

            case ConsoleKey.DownArrow:
                Selected++;
                break;

            case ConsoleKey.UpArrow:
                Selected--;
                break;

            case ConsoleKey.Q:
                IsRunning = false;
                break;
        }
    }
}

这里有一个类似的方法,代码稍微少一点,它隐藏光标并显示我们自己的自定义光标,指示所选的菜单项

该方法包含一个菜单头、一个供用户选择的选项列表和一个光标字符。它打印出标题和下划线,然后在每个选项前面加上3个空格。然后我们将光标移动到第一个选项(行索引3,因为标题为0,下划线为1,空格为2),第二个字符,然后写一个退格字符,后跟光标(退格删除第一个字符,以便我们可以写一个新字符)

当用户按键时,我们只处理上下箭头和回车键。通过将
true
传递到
Console.ReadKey()
,用户输入被“丢弃”,不会显示在窗口上。这允许我们只打开我们关心的按键

当他们按箭头键时,我们将光标移动到当前行的第二列,然后打印一个空格和一个空格(以擦除旧光标),然后向上或向下移动一行,然后从第二列打印一个空格和光标字符

当用户按Enter键时,我们再次启用控制台光标,并返回光标所在的行,以指示当时选择了哪个项目:

private static int GetMenuChoice(string header, List<string> options, char cursor = '>')
{
    // Clear console and hide cursor
    Console.Clear();
    Console.CursorVisible = false;

    // Write our header with an underline
    Console.WriteLine("   " + header);
    Console.WriteLine("   " + new string('-', header.Length));
    Console.WriteLine();

    // Write out each option with spaces before it
    options.ForEach(option => Console.WriteLine($"   {option}"));

    // Move to the first option and, from the second character,
    // write a backspace and then the cursor symbol
    Console.SetCursorPosition(1, 3);
    Console.Write($"\b{cursor}");

    // Move cursor when user presses arrow keys, and get selection when they press enter
    while (true)
    {
        // Pass 'true' to ReadKey so the input is not written
        var input = Console.ReadKey(true);

        switch (input.Key)
        {
            case ConsoleKey.UpArrow:
                if (Console.CursorTop > 3)
                {
                    Console.CursorLeft = 1;
                    Console.Write("\b ");
                    Console.SetCursorPosition(1, Console.CursorTop - 1);
                    Console.Write($"\b{cursor}");
                }
                break;

            case ConsoleKey.DownArrow:
                if (Console.CursorTop < options.Count + 2)
                {
                    Console.CursorLeft = 1;
                    Console.Write("\b ");
                    Console.SetCursorPosition(1, Console.CursorTop + 1);
                    Console.Write($"\b{cursor}");
                }
                break;

            case ConsoleKey.Enter:
                var selection = Console.CursorTop - 3;
                Console.CursorVisible = true;
                Console.SetCursorPosition(0, options.Count + 4);
                return selection;
        }
    }
}
private static int GetMenuChoice(字符串头,列表选项,字符光标='>'))
{
//清除控制台并隐藏光标
Console.Clear();
Console.CursorVisible=false;
//用下划线写标题
Console.WriteLine(“+”标题);
WriteLine(“+新字符串('-',header.Length));
Console.WriteLine();
//在每个选项前面写上空格
options.ForEach(option=>Console.WriteLine($“{option}”);
//移动到第一个选项,然后从第二个字符开始,
//写一个空格,然后写光标符号
控制台。设置光标位置(1,3);
Write($“\b{cursor}”);
//用户按箭头键时移动光标,按enter键时获取选择
while(true)
{
//将“true”传递给ReadKey,以便不写入输入
var input=Console.ReadKey(true);
开关(输入键)
{
case ConsoleKey.UpArrow:
如果(Console.CursorTop>3)
{
Console.CursorLeft=1;
控制台。写入(“\b”);
Console.SetCursorPosition(1,Console.CursorTop-1);
Write($“\b{cursor}”);
}
打破
case ConsoleKey.DownArrow:
if(Console.CursorTop
这可以通过示例ATM菜单进行测试:

private static void Main()
{
    var options = new List<string>
    {
        "Open a new account",
        "Deposit Money",
        "Withdraw money",
        "Check balance",
        "Exit"
    };

    var selectedItem = GetMenuChoice("ATM Machine", options);

    Console.WriteLine($"You selected option: '{options[selectedItem]}'");

    GetKeyFromUser("\nDone! Press any key to exit...");
}
private static void Main()
{
var options=新列表
{
“开立新帐户”,
“存款”,
“取款”,
“核对余额”,
“退出”
};
var selectedItem=GetMenuChoice(“ATM机”,选项);
WriteLine($“您选择的选项:{options[selectedItem]}”);
GetKeyFromUser(“\n完成!按任意键退出…”);
}
输出


您好,您可能希望的是,然后再次写入输出。如果要覆盖现有输出,而不是每次都清除屏幕,您可以使用
Console.SetCursorPosition()