3

簡単な小さなゲームを作って、C#スレッドの使い方を学ぼうとしています。私は確かに助けを使うことができる少しの問題に遭遇しました。

私の望みは、入力と出力を同時に行うことです。スレッドからの出力は画面の上部に表示され、ユーザーの入力は画面の下部に入力できます。私が遭遇している問題は、画面を更新するために、を使用するConsole.Clear()と、ユーザーが入力しているものがすべて消去されることです。以下に、私がやろうとしていることの非常に単純化されたバージョンを添付しました(実際の問​​題の邪魔になる不要なコードを避けるため)。

注:この例では、画面上部の1文字のみを更新していますが、実際のプログラムでは、画面の上部と中央全体に大量のテキストがあり、ティックごとに絶えず変化します(これは私が計画しています)。 1.5秒で使用します)。

どんなアイデアでも素晴らしいでしょう!私はまだC#プログラミングに不慣れであり、あなたが与えることができるどんな助けにもわくわくするでしょう:)ここで私が執着している唯一のものはデザインです。一番上にシステム出力、一番下にユーザー入力の前に「>」があります。私がそれをしている方法が間違っている場合、私はそれをすべて窓の外に投げ出し、それを別の方法で行うことに問題はありません。

編集:ここでの私の目標は、ユーザーが画面の下部に入力できるようにしながら、画面上部の出力テキストを1.5秒ごと(カウントスレッドの実行ごと)に更新することです。ただし、これを行うために使用している方法(クリアしてから画面に新しいコンテンツを書き込む)でも、ユーザーの入力が消去されます。これにより、ユーザーが入力している入力が1.5秒ごとに消えてしまいます。これは、Console.Clearが行うこととまったく同じだからです。だから私はこのタスクを達成するための新しい方法を探しています。

つまり、ユーザーが画面の下部で入力を続けられるようにしながら、画面の上部/中央のテキストを更新するにはどうすればよいですか?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace ConsoleApplication2
{
    class Program
    {

        static int i = 0;

        static void Main(string[] args)
        {
            Thread tickThread = new Thread(new ThreadStart(CountThread));
            Thread userThread = new Thread(new ThreadStart(UserInput));
            tickThread.Start();
            Thread.Sleep(1);
            userThread.Start();
            Thread.Sleep(20000);
            tickThread.Abort();
            userThread.Abort();
        }

        static void UserInput()
        {
            string input = "";
            while (true)
            {
                input = Console.ReadLine();
            }
        }


        static void CountThread()
        {
            while (true)
            {
                Console.Clear();
                Console.SetCursorPosition(0, 0);
                Console.WriteLine(i);
                i++;
                Console.SetCursorPosition(0, Console.WindowHeight - 1);
                Console.Write("> ");
                Thread.Sleep(1500);

            }
        }

    }
}
4

4 に答える 4

1

を使用して文字で入力文字を読み取ることができますConsole.ReadKey。入力を保存すると、コンソールがクリアされる前に入力された入力を含め、画面全体を再構築できます。すべてのI/O関連を1つのスレッドで実行することをお勧めします。複数のスレッドによって更新されるコンソールの内部表現を保持し、それを1つのスレッドから印刷することができます。

これを行う!

于 2012-07-24T10:53:23.660 に答える
1

ユーザー入力用に設計されたセルを除き、コンソールの各セルのループ内でカーソル位置を設定し、スペース記号を書き込むことができます。これにより、基本的に、コンソールウィンドウの一部がクリアされます。また、同じ方法を使用して、コンソールへの出力を部分的にレンダリングすることもできます。

于 2012-07-24T10:10:47.033 に答える
0

そのためにウィンドウフォームを使用することを検討しましたか?出力用に1つのパネルがあり、入力用に1つのパネルがありますか?

于 2012-07-24T10:16:54.083 に答える
0

これは、メインスレッドがコンソール入力を読み取り、2番目のスレッドがコンソール出力を書き込むアプローチです。

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;

namespace ConsoleReadWriteTest
{
    class Program
    {
        private static ConsoleInfo consoleInfo = new ConsoleInfo();
        static void Main(string[] args)
        {
            Thread consoleWriter = new Thread(new ThreadStart(ConsoleWriter));
            consoleWriter.Start();

            consoleInfo.outputBuffer.Add("Running.");
            consoleInfo.outputBuffer.Add(".. status of foo = good");
            consoleInfo.outputBuffer.Add(".. status of bar = bad");

            while (true)
            {
                var key = Console.ReadKey(true);
                lock (consoleInfo)
                {
                    if (key.Key == ConsoleKey.Enter)
                    {
                        consoleInfo.commandReaty = true;
                    }
                    else
                    {
                        consoleInfo.sbRead.Append(key.KeyChar.ToString());
                    }
                }
            }

        }

        static void ConsoleWriter()
        {
            while (true)
            {
                lock(consoleInfo)
                {
                    Console.Clear();

                    if (consoleInfo.outputBuffer[0].Length > 20)
                    {
                        consoleInfo.outputBuffer[0] = "Running.";
                    }
                    else
                    {
                        consoleInfo.outputBuffer[0] += ".";
                    }

                    foreach (var item in consoleInfo.outputBuffer)
                    {
                        Console.WriteLine(item);
                    }

                    Console.WriteLine("--------------------------------------------------------------");

                    if (consoleInfo.commandReaty)
                    {
                        consoleInfo.commandReaty = false;
                        consoleInfo.lastCommand = consoleInfo.sbRead.ToString();
                        consoleInfo.sbRead.Clear();
                        consoleInfo.lastResult.Clear();
                        switch (consoleInfo.lastCommand)
                        {
                            case "command1":
                                consoleInfo.outputBuffer[2] = ".. status of bar = good";
                                consoleInfo.lastResult.Append("command #1 performed");

                                break;
                            case "command2":
                                consoleInfo.outputBuffer[2] = ".. status of bar = bad";
                                consoleInfo.lastResult.Append("command #2 performed");
                                break;
                            case "?":
                                consoleInfo.lastResult.AppendLine("Available commands are:");
                                consoleInfo.lastResult.AppendLine("command1     sets bar to good");
                                consoleInfo.lastResult.AppendLine("command1     sets bar to bad");
                                break;
                            default:
                                consoleInfo.lastResult.Append("invalid command, type ? to see command list");
                                break;
                        }
                    }

                    Console.WriteLine(consoleInfo.lastCommand);
                    Console.WriteLine(consoleInfo.lastResult);
                    Console.WriteLine();
                    Console.Write(">");
                    Console.WriteLine(consoleInfo.sbRead.ToString());
                    Console.WriteLine();
                    Console.WriteLine();
                    Console.WriteLine();
                }

                Thread.Sleep(250);
            }
        }
        private class ConsoleInfo
        {
            public bool commandReaty { get; set; }
            public StringBuilder sbRead { get; set; }
            public List<string> outputBuffer { get; set; }
            public string lastCommand { get; set; }
            public StringBuilder lastResult { get; set; }

            public ConsoleInfo()
            {
                sbRead = new StringBuilder();
                outputBuffer = new List<string>();
                commandReaty = false;
                lastResult = new StringBuilder();
            }
        }
    }
}
于 2017-09-22T03:44:33.363 に答える