老周是一個不喜歡做介面的碼農,所以很多時候能用控制檯互動就用控制檯互動,既方便又佔資源少。有大夥伴可能會說,控制檯全靠打字,不好互動。那不一定的,像一些選項類的互動,可以用鍵盤按鍵(如方向鍵),可比用滑鼠快得多。當然了,要是要觸控的話,是不太好用,只能做UI了。
關於控制檯互動,大夥伴們也許見得最多的是進度條,就是輸出一行但末尾不加 \n,而是用 \r 回到行首,然後輸出新的內容,這樣就做出進度條了。不過這種方法永遠只能修改最後一行文字。
於是,有人想出了第二種方案——把要輸出的文字存起來(用二維陣列,啥的都行),每次更新輸出時把螢幕內容清空重新輸出。這就類似於視窗的重新整理功能。缺點是文字多的時候會閃屏。
綜合來說,區域性覆蓋是最優方案。就是我要修改某處的文字,我先把遊標移到那裡,覆蓋掉這部分內容即可。這麼一來,咱們得了解,在控制檯程式中,遊標是用行、列定位的。其移動的單位不是畫素,是字元。比如 0 是第一行文字,1 是第二行文字……對於列也是這樣。所以,(2, 4) 表示第三行的第五個字元處。這個方案是核心原理。
當然了,上述方案只是程式展示給使用者看的,若配合使用者的鍵盤輸入,互動過程就完整了。
下面給大夥伴們做個演示,以便了解其原理。
internal class Program { static void Main(string[] args) { // 我們先輸出三行 Console.WriteLine("===================="); Console.WriteLine("你好,小子"); Console.WriteLine("===================="); // 我們要改變的是第二行文字 // 所以top=1 int x = 10; do { // 重新定位遊標 Console.SetCursorPosition(0, 1); Console.Write("離爆炸還剩 {0} 秒", x); Thread.Sleep(1000); } while ((--x) >= 0); Console.SetCursorPosition(0, 1); Console.Write("Boom!!"); Console.Read(); } }
SetCursorPosition 方法的簽名如下:
public static void SetCursorPosition(int left, int top);
left 引數是指遊標距離控制檯視窗左邊沿的位移,top 引數指定的是遊標距離視窗上邊沿的位移。因此,left 表示的是列,top 表示的是行。都是從 0 開始的。
你得注意的是,在覆蓋舊內容的時候,要用 Write 方法,不要呼叫 WriteLine 方法。你懂的,WriteLine 方法會在末尾產生換行符,那樣會破壞原有文字的佈局的,覆寫後會出現N多空白行。
咱們看看效果。
生成點陣圖時,尺寸不要太大,不然很佔螢幕。畢竟控制檯是以字元來計量的,不是畫素。