簡體   English   中英

如何在控制台應用程序中同時寫多個位置? C#

[英]How to write in multiple positions in a console application at the same time? C#

我想要與控制台寬度一樣多的行同時向下寫一個字符到控制台的高度。 我已經完成了大部分工作,但它從上到下依次為...

如果您需要幫助來描繪我的意思,請考慮矩陣碼降雨。

int w = Console.WindowWidth;
int h = Console.WindowHeight;

int i = 0;
while (i < w)
{
    int j = 0;
    while (j < h)
    {
        Thread.Sleep(1);
        Console.SetCursorPosition(i, j);
        Console.Write(".");
        j++;
    }
    i++;
}

我要做的是構造一個List<string> lines; 包含要寫入控制台窗口的行,其中每行與控制台寬度一樣寬。 然后只需按相反順序將列表打印到控制台窗口,因此第一行(在行lines[0] )將始終是最后一行打印,並始終位於控制台窗口的底部。


示例實施 - 有人提到這可能是家庭作業。 我不這么認為,但如果是的話,請先嘗試自己實現上述想法。

我們可以在用於打印其項目的同一循環中將新項添加到列表中。 然而,在我們添加一行之前,我們首先檢查列表中是否有與控制台窗口( Console.WindowHeight )中一樣多的行。 如果有,那么我們只需刪除第lines[0]行,然后再添加新行。 這樣, List<string> lines與控制台窗口一起“滾動”。

滾動速度由Thread.Sleep控制,但是這個代碼可以很容易地添加到Timer ,這樣其他工作可能會在后台發生(就好像這是一個“屏幕保護程序”,你想要等待用戶輸入“喚醒”)。 但無論我們如何決定實現速度,我決定創建一個enum ,其值表示Thread.Sleep實現將使用的毫秒數:

class Program
{
    enum MatrixCodeSpeed
    {
        Fastest = 0,
        Faster = 33,
        Fast = 67,
        Normal = 100,
        Slow = 333,
        Slower = 667,
        Slowest = 1000
    }

我還會創建一個幫助方法,為您創建一個“隨機”行。 它可以采用一個指定“密度”的整數,這意味着你需要在行中有多少個字符。 density表示一個百分比,所以如果指定10 ,那么我們選擇0到99之間的隨機數,如果它小於10,那么我們在字符串中添加一個隨機矩陣字符(否則我們添加一個空格字符)。

另外,為了更接近地復制矩陣,我還選擇了4個不同的字符進行打印,每個字符都比前一個稍暗。 這增加了三維效果,其中褪色塊看起來比實體塊更遠:

    private static Random rnd = new Random();

    // Add whatever 'matrix' characters you want to this array. If you prefer to have one 
    // character chosen more often than the others, you can write code to favor a specific
    // index, or just add more instances of that character to the array below:

    private static char[] matrixChars = new[] { '░', '▒', '▓', '█' };

    static string GetMatrixLine(int density)
    {            
        var line = new StringBuilder();

        for (int i = 0; i < Console.WindowWidth; i++)
        {
            // Choose a random number from 0-99 and see if it's greater than density
            line.Append(rnd.Next(100) > density 
                ? ' '  // If it is, add a space to reduce line density
                : matrixChars[rnd.Next(matrixChars.Length)]); // Pick a random character
        }

        return line.ToString();
    }

接下來,我們有一個main方法,用隨機線填充一個列表(使用10%的密度),然后以相反的順序一次打印出一個無限循環(如果需要,刪除第一行) ):

    static void Main()
    {
        var lines = new List<string>();
        var density = 10; // (10% of each line will be a matrix character)
        var speed = MatrixCodeSpeed.Normal;

        // Hide the cursor - set this to 'true' again before accepting user input
        Console.CursorVisible = false;
        Console.ForegroundColor = ConsoleColor.DarkGreen;

        while (true)
        {
            // Once the lines count is greater than the window height,
            // remove the first item, so that the list "scrolls" also
            if (lines.Count >= Console.WindowHeight)
            {
                lines.Remove(lines[0]);
            }

            // Add a new random line to the list, which will be the new topmost line.
            lines.Add(GetMatrixLine(density));
            Console.SetCursorPosition(0, 0);

            // Print the lines out to the console in reverse order so the
            // first line is always last, or on the bottom of the window
            for (int i = lines.Count - 1; i >= 0; i--)
            {
                Console.Write(lines[i]);
            }

            Thread.Sleep(TimeSpan.FromMilliseconds((int)speed));
        }
    }
}

這是一個實際的GIF,直到屏幕已滿(然后gif重復,但代碼版本繼續正常滾動):

在此輸入圖像描述

任務聞起來像一個任務,所以我指導你而不是喂養實現。 如果是家庭作業,給你答案是不合乎道德的。

您正在尋找更好的算法。 所述算法從上到下填充控制台,因為它迭代以首先填充Y軸(嵌套循環),然后是X軸(外循環)。

所需要的是交替迭代x軸和y軸 ,使其看起來像是從左上角到右下角填充。

// 1 step to (0,0)
*
// 3 steps to (1,1)
**
**
// 5 steps for reaching (2,2)
***
***
***
// 7 steps for reaching (3,3)
****
****
****
// 9 steps for reaching (4,4) and 11 steps for (5,5)...
// I do think everyone could get this pattern

該草案也將是它的樣子的最終結果。 而不是同時填充它們,你需要的是在線程到達下一個方格點后實際上讓它休眠。 (計算機速度如此之快,以至於它可能會在一秒鍾內完成所有工作,並且黑色控制台窗口消失,而沒有任何通知。)

在你發布問題時,我也是從一開始就解決它。 我認為填充X和Y軸是另一種解決方案,但每次廣場擴展時停止對於獲得效果更為重要。

在我看來,它不是線程問題標記。

讓我們總結一下上面的模式:

  1. 假設i和j分別是x和y坐標。
  2. 每次迭代都會從(i,j)和n * 2 + 1步驟到達(i + 1,j + 1)
  3. 請注意,在此示例中,我們從零開始。

我們即將構建循環:

  • n * 2 + 1步驟編號很有用。 這意味着你需要將x軸填充n次,將y軸填充n次,最后得到對角網格(n + 1,n + 1)。
  • 在每個內循環中,我們首先沿y軸渲染X前沿,然后沿x軸渲染Y前沿。
  • 假設循環從檢查點(n,n)開始,其中n = 3,我們睡了一會兒,所以我們現在在n = 4。
  • 要實現這一點,我們最好首先導航到(n + 1,0)然后填充到(n + 1,n)
  • 然后我們導航到(0,n + 1)並填充到(n + 1,n + 1)
  • 然后我們現在在m = n + 1(聽起來像一個數學證明:(

循環將是

//calculate how many checkpoints (n)
int checkpoints = 1080;
//n should indicate the actual turn we are instead of naming the total turns like sucks
//The main, the outermost For-loop 
for (int n=0;n<checkpoints;n++)
{
  // The nested step
  for (int y=0;y<n;y++)
  {
    // Just fill in (n+1, y) grid 
    Console.SetCursorPosition(n+1, y);
    Console.Write(".");
  }
  for (int x=0;x<n+1;x++) 
  {         
    // Just fill in (x, n+1) grid
    Console.SetCursorPosition(x, n+1);
    Console.Write(".");
  }
  // Upon completion of each main cycle we have a sleep, yah
  Thread.Sleep(100);
}

好吧,我希望程序在控制台大小小於1080x1080時崩潰。

這個算法只能得到一個正方形來填充,而分辨率為1920x1080的典型監視器就會失敗,因為它是16:9。 這是故意的,如果您正在做作業,則需要先將其配置,然后再將其發送給您的老師。 (因為我自學編程,我沒有機會做任務:(

(該網站不斷敦促我格式化我的代碼,這已經有半個小時了,我只是沒有做錯。所以我決定一點一點地發布它來調試。最后我完成了工作.. 。)

如果您只想一次寫一行,可以使用:

int w = Console.WindowWidth;
int h = Console.WindowHeight;

int i = 0;

while (i < h)
{
    Console.WriteLine(new string('.', w-1));
    Thread.Sleep(20);
    i++;
}

只需稍加修改即可讓代碼模擬矩陣碼降雨。

    int w = Console.WindowWidth;
    int h = Console.WindowHeight;

    int i = 0;
    while (i < h)
    {
        int j = 0;
        string s = "";
        Thread.Sleep(10);
        while (j < w)
        {
            Console.SetCursorPosition(j, i);
            s += ".";
            j++;
        }
        Console.Write(s);
        i++;
    }

基本上我在這里所做的只是對邏輯進行一些重組,並在正確的位置進行適當的延遲。 希望能幫助到你。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM