我会构建一个名为
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();
private static char[] matrixChars = new[] { '░', '▒', '▓', '█' };
static string GetMatrixLine(int density)
{
var line = new StringBuilder();
for (int i = 0; i < Console.WindowWidth; i++)
{
line.Append(rnd.Next(100) > density
? ' '
: matrixChars[rnd.Next(matrixChars.Length)]);
}
return line.ToString();
}
接下来,我们有一个主方法,它使用10%的密度将列表填充了随机行,然后以相反的顺序一次打印出它们,进入无限循环(如果需要,则删除第一行)。
static void Main()
{
var lines = new List<string>();
var density = 10;
var speed = MatrixCodeSpeed.Normal;
Console.CursorVisible = false;
Console.ForegroundColor = ConsoleColor.DarkGreen;
while (true)
{
if (lines.Count >= Console.WindowHeight)
{
lines.Remove(lines[0]);
}
lines.Add(GetMatrixLine(density));
Console.SetCursorPosition(0, 0);
for (int i = lines.Count - 1; i >= 0; i--)
{
Console.Write(lines[i]);
}
Thread.Sleep(TimeSpan.FromMilliseconds((int)speed));
}
}
}
这里是它的演示gif,直到屏幕满了为止(然后gif会重复播放,但代码版本会继续正常滚动):