c# - 如何在控制台上的 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);
}
}
}
解决方案
不确定这是否正是您要查找的内容,但这是一种在屏幕上绘制矩形,然后在用户按下其中一个箭头键时移动它的方法(您仍然需要添加逻辑以将矩形保留在其中控制台窗口的边界)。
请注意,性能可以通过仅“擦除”原始矩形中不与新矩形重叠的部分来提高,但至少它是移动矩形的开始。另外,当我在我的机器上运行它时,我看不到任何闪烁。
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...");
}
推荐阅读
- html - 如何使用 HTML 和 CSS 修复导航栏汉堡
- python - 尝试访问 Django 应用程序中上传的文件时出错
- node.js - 为什么没有用新余额更新商店文件?节点+猫鼬快递
- java - inverseJoinColumns 是强制性的吗?
- python - 如何将实例方法用作 APscheduler 的作业并与持久数据存储结合使用 [未绑定方法错误]
- orchardcms - Orchard Core 中的默认管理菜单?
- networking - 客户端可以在没有 pppoe 设置(Juniper srx300)的情况下从内部连接到互联网吗?
- roku - BrightScript 函数返回字符串有时会返回自身(函数)
- drupal - 如何通过表单提交在特定节点(内容)类型上添加链接任务(选项卡)?
- php - 根据用户输入创建动态多关联数组