【问题标题】:How to update for loop result in Console.WriteLine without creating new line?如何在不创建新行的情况下更新 Console.WriteLine 中的 for 循环结果?
【发布时间】:2019-12-26 18:10:06
【问题描述】:

此代码显示的结果如下:

distance from target : 10
distance from target : 9
distance from target : 8
(line by line)

我想显示结果,比如与目标的距离:10,然后用 9、8、7 替换 10 的位置,(只有 10 的位置会更新)

public void Attack()
{
    for (int i = 1; i < 3; i++)
    {
        if (i == 1)
        {
            Console.WriteLine("Target Locked (+)");
            Thread.Sleep(2000);
        }
        if (i == 2)
        {
            Console.WriteLine("Fired!");
            Thread.Sleep(1000);
        }
    }
    Random random = new Random();
    int distance = random.Next(100, 3000);
    for (int i = distance; i > 0; i = i - 3)
    {
        Console.WriteLine("distance from target : " + i);
        Thread.Sleep(30);
        //Console.Clear();
    }
    Console.WriteLine("BloooW!");
}

【问题讨论】:

  • 查看控制台类中的这些属性:CursotTop、CursorLeft 和 SetCursorPosition 这个方法
  • 如果我理解你正确.. 尝试使用 Console.Write() 而不是 Console.WriteLine()
  • @G.Y 我认为他希望他的输出从10 更改为9 等,而不是10, 9, 8, 7,...
  • 另外,如果您知道总数,您可以将数字填充到最大数字的宽度。如果合适的话。然后文本行的宽度一直保持不变。

标签: c# .net loops iteration console-application


【解决方案1】:

您可以使用 CursorTop、CursorLeft 和 SetCursorPosition 来精细控制写入输出的位置。但真正的诀窍是删除你之前在那个地方写的东西。在这里您可以使用 Console.Write/WriteLine 的格式字符串功能

    // This needs to be written just one time
    Console.Write("distance from target : ");
    // Now get the current cursor position after the write above
    int posX = Console.CursorLeft;
    int posY = Console.CursorTop;


    for (int i = distance; i > 0; i = i - 3)
    {
        // Position the cursor where needed
        Console.SetCursorPosition(posX, posY);

        // Replace the previous write with a number aligned on the left on 4 spaces
        Console.Write($"{i,-4:D}");
        // As an alternative to SetCursorPosition you could have
        // Console.CursorLeft -= 4;
        // but, to me this is less clear....

        Thread.Sleep(30);
    }
    // Do not forget to jump to the next line
    Console.WriteLine("\r\nBloooW!");

【讨论】:

  • 谢谢,它既棘手又好用。但我认为应该有一些更好的方法来解决这个问题。
  • 不知道有没有更好的办法。也许像用你自己的替换控制台类,或者控制控制台使用的输入/输出流。不确定他们是否值得花时间进一步调查。实际上这就是标准控制台的工作方式。每次编写 x,y 位置时都会更改以反映新的输出点。如果您想更改该点,您可以使用 CursorTop 和 CursorLeft 进行此操作
【解决方案2】:

您可以将Console.WriteLine 更改为Console.Write,在字符串前面添加\r

        for (int i = distance; i > 0; i = i - 3)
        {
            Console.Write("\rdistance from target : " + i);
            Thread.Sleep(30);
            //Console.Clear();
        }
        Console.WriteLine("");

这将导致控制台返回到行首并再次写入字符串,覆盖上次写入时存在的字符串。还要确保在 for 循环之后添加 Console.WriteLine(""); 以移动到下一行,这样您的下一次写入不会从该行开始。

如果您的字符串只会变长,此解决方案效果最佳。

如果你的字符串会变短,你可以在字符串末尾添加一些空格,如下所示:

 Console.Write("\rdistance from target : {0} ", i);

当您从 10 转到 9 时,就是这种情况

【讨论】:

    【解决方案3】:

    那么你应该先删除写入控制台的距离,可以通过一个或多个退格来完成\b

    改变

    for (int i = distance; i > 0; i = i - 3)
                {
                    Console.WriteLine("distance from target : " + i);
                    Thread.Sleep(30);
                    //Console.Clear();
                }
    

    int lastDistanceLength = 0; // save the last number of distance chars written
    
    for (int i = distance; i > 0; i = i - 3)
    {
       if(lastDistanceLength == 0) { // no distance chars written yet.
           Console.Write("distance from target : " + i);
        } 
        else  { 
           for(int j=0;j‹lastDistanceLength;j++)
              Console.Write("\b"); // delete old distance
           Console.Write(""+i);
    
        }
        lastDistanceLength = i==10 ? 2 : 1;           
        Thread.Sleep(30);
        //Console.Clear();
    }
    Console.WriteLine("\r\nBloooW!");
    

    您很可能需要更高级的算法来计算 lastDistanceLength,也许只需将 i 转换为字符串并取长度,例如lastDistanceLength = (""+i).Length

    这里有相当全面的解释:Is there a way to delete a character that has just been written using Console.WriteLine?

    【讨论】:

      【解决方案4】:

      你可以像这样使用 Console.CursorTop :

      for (int i = distance; i > 0; i = i - 3)
      {
          Console.WriteLine("distance from target : " + i + "    "); // dirty trick to erase longer previous numbers
          Thread.Sleep(30);
          Console.CursorTop--;
      }
      Console.CursorTop++; // so that we advance to the next line after the loop.
      

      它将光标向上移动一行,因此后续调用会覆盖之前在上一行中的内容。

      这种方法不是最有效的,因为它会重写整行,但它很简单,从用户的角度来看,只会更新数值。

      如果性能差异如此之小,您可以尝试将光标位置更精确地设置为数值开始的位置。我不确定这是否可行,但如果重要的话值得一试。

      【讨论】:

        猜你喜欢
        • 2021-06-16
        • 2013-04-11
        • 2014-02-23
        • 1970-01-01
        • 2017-01-20
        • 2021-04-11
        • 1970-01-01
        • 1970-01-01
        • 2019-12-14
        相关资源
        最近更新 更多