我想要与控制台宽度一样多的行同时向下写一个字符到控制台的高度.我已经完成了大部分工作,但它从上到下依次为…
如果您需要帮助来描绘我的意思,请考虑矩阵码降雨.
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>线;包含要写入控制台窗口的行,其中每行与控制台宽度一样宽.然后只需按相反顺序将列表打印到控制台窗口,因此第一行(在行[0])将始终是最后一行打印,并始终位于控制台窗口的底部.
示例实施 – 有人提到这可能是家庭作业.我不这么认为,但如果是的话,请先尝试自己实现上述想法.
我们可以在用于打印其项目的同一循环中将新项添加到列表中.然而,在我们添加一行之前,我们首先检查列表中是否有与控制台窗口(Console.WindowHeight)中一样多的行.如果有,那么我们只需删除第[0]行,然后再添加新行.这样,List< string> lines与控制台窗口一起“滚动”.
滚动速度由Thread.Sleep控制,但是这个代码可以很容易地添加到Timer中,这样其他工作可能会在后台发生(就好像这是一个“屏幕保护程序”,你想要等待用户输入“唤醒”).但无论我们如何决定实现速度,我决定创建一个枚举,其值表示Thread.Sleep实现将使用的毫秒数:
class Program { enum MatrixCodeSpeed { Fastest = 0,Faster = 33,Fast = 67,Normal = 100,Slow = 333,Slower = 667,Slowest = 1000 }
我还会创建一个帮助方法,为您创建一个“随机”行.它可以采用一个指定“密度”的整数,这意味着你需要在行中有多少个字符.密度表示一个百分比,所以如果指定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重复,但代码版本继续正常滚动):