首页 > 解决方案 > 如何在控制台上的 x 坐标上移动字符串的所有字符

问题描述

我正在开发一个绘制形状的控制台应用程序,我正在尝试的概念证明是正方形。在这种情况下,我正在寻找一种将正方形平滑地向右移动的方法。我有一个解决方案可以做到这一点,但是它在闪烁。我想要的是一些解决方案,可以让我移动正方形而不会闪烁。我这样做是为了好玩,并一点一点地编写一个自定义控制台游戏引擎,用于学习目的。任何帮助,将不胜感激。另外,我还没有使用 GDI+ 或 system.drawing,我稍后会添加。这是一些代码:

static void DrawRectangle()
{
    int height = 10; //height of square
    int width = 20; //width of square
    int coordinateY = height - 1;
    int coordinateX = width - 1;
    int firstPositionY = 0; //to track cursor position in Y
    int firstPositionX = 0; //to track cursor position in X
    char[][] c = new char[height][];
    //buffer of console. Be aware that the shape to be drawn isn't larger than the actual console buffer
    Console.BufferHeight = 30;
    Console.BufferWidth = 120;
    //Font and background color
    Console.ForegroundColor = ConsoleColor.Blue;
    //Console.BackgroundColor = ConsoleColor.Cyan;
    //Formula to start drawing in the center of the buffered console
    firstPositionX = (Console.BufferWidth - width) / 2;
    firstPositionY = (Console.BufferHeight - height) / 2;
    //set initial cursor position to the results of the above calculation
    Console.Beep();
    Console.SetCursorPosition(firstPositionX, firstPositionY);
    for (int y = 0; y < height; y++)
        c[y] = new char[width];
    //draws top line of the square
    c[0][0] = '\u2554';
    Console.Write(c[0][0]);
    for (int x = 1; x < width; x++)
    {
        Thread.Sleep(15);
        c[0][x] = '\u2550';
        Console.Write(c[0][x]);
    }
    for (int y = 1; y < height; y++)
    {
        Thread.Sleep(20);
        //keeps track of the cursor, so it draws vertically
        Console.SetCursorPosition(firstPositionX, firstPositionY + y);
        c[y][0] = '\u2551';
        Console.WriteLine(c[y][0]);
    }
    //Set cursor position to the other side top right of the square
    Console.SetCursorPosition(width + firstPositionX, firstPositionY);
    c[coordinateY][coordinateX] = '\u2557';
    Console.Write(c[coordinateY][coordinateX]);
    for (int y = 1; y < height; y++)
    {
        Thread.Sleep(20);
        Console.SetCursorPosition(width + firstPositionX, firstPositionY + y);
        c[y][coordinateX] = '\u2551';
        Console.WriteLine(c[y][coordinateX]);
    }
    Console.SetCursorPosition(firstPositionX, firstPositionY + height);
    for (int x = 0; x <= coordinateX; x++)
    {
        Thread.Sleep(15);
        c[coordinateY][x] = '\u2550';
        Console.Write(c[coordinateY][x]);
    }
    //square corners
    Console.SetCursorPosition(firstPositionX, firstPositionY + height);
    Console.Write("\u255A");
    Console.SetCursorPosition(firstPositionX + width, firstPositionY + height);
    Console.Write("\u255D");
    //fill the square with solid blocks
    for (int y = 1; y < height; y++)
    {
        Console.SetCursorPosition(firstPositionX + 1, firstPositionY + y);
        for (int x = 1; x < width; x++)
        {
            c[y][x] = '\u2588';
            Console.Write(c[y][x]);
            Thread.Sleep(7);
        }
    }
    //pass matrix to string for easier handling? Will fix later
    string s = string.Empty;
    for (int y = 0; y < height; y++)
    {
        for (int x = 0; x < width; x++)
            s += c[y][x];
        s += "\n";
    }
    while (true)
    {
        while (Console.ReadKey().Key == ConsoleKey.RightArrow)
        {
            Console.Clear();
            Thread.Sleep(3);
            Console.SetCursorPosition(firstPositionX += 1, firstPositionY);
            Console.ForegroundColor = ConsoleColor.Blue;
            Console.Write(s);
        }
    }
}

标签: c#

解决方案


不确定这是否正是您要查找的内容,但这是一种在屏幕上绘制矩形,然后在用户按下其中一个箭头键时移动它的方法(您仍然需要添加逻辑以将矩形保留在其中控制台窗口的边界)。

请注意,性能可以通过仅“擦除”原始矩形中不与新矩形重叠的部分来提高,但至少它是移动矩形的开始。另外,当我在我的机器上运行它时,我看不到任何闪烁。

static void DrawRectangle(Rectangle rect, ConsoleColor color = ConsoleColor.Blue, 
    char fill = '█')
{
    var foreColor = Console.ForegroundColor;
    Console.ForegroundColor = color;
    Console.SetCursorPosition(rect.Left, rect.Top);

    for (int i = 0; i < rect.Height; i++)
    {
        Console.Write(new string(fill, rect.Width));
        Console.SetCursorPosition(rect.Left, Console.CursorTop + 1);
    }

    Console.ForegroundColor = foreColor;
}     

private static void Main()
{
    Console.CursorVisible = false;

    // Draw a rectangle
    var rect = new Rectangle(10, 10, 10, 5);
    DrawRectangle(rect);

    // Move the rectangle when the user presses an arrow key
    while (true)
    {
        // Wait for a key press
        while (!Console.KeyAvailable) ;

        // "Erase" the current rectangle
        DrawRectangle(rect, Console.BackgroundColor);

        // Set the location for the new rectangle based on the key that was pressed
        switch (Console.ReadKey().Key)
        {
            case ConsoleKey.UpArrow:
            {
                var location = new Point(rect.X, rect.Y - 1);
                rect = new Rectangle(location, rect.Size);
                break;
            }
            case ConsoleKey.DownArrow:
            {
                var location = new Point(rect.X, rect.Y + 1);
                rect = new Rectangle(location, rect.Size);
                break;
            }
            case ConsoleKey.LeftArrow:
            {
                var location = new Point(rect.X - 1, rect.Y);
                rect = new Rectangle(location, rect.Size);
                break;
            }
            case ConsoleKey.RightArrow:
            {
                var location = new Point(rect.X + 1, rect.Y);
                rect = new Rectangle(location, rect.Size);
                break;
            }
        }

        // Draw the new rectangle
        DrawRectangle(rect);
    }

    GetKeyFromUser("\n\nDone! Press any key to exit...");
}

推荐阅读