Как сделать красивый вывод текста на C#

от автора

Пролог

Прошлый пост на счет сердечка посмотрело много людей и у меня возникла идея сделать еще одну простенькую, но достаточно красивую штуку, а именно такой вот вывод текста(можно сказать анимированного, но язык не поворачивается). Данный пост подходит для новичков, можно потренироваться в использовании массивов, циклов, немного классов и методов.

Экспозиция 

Создаем класс «Print», и в нем создаем приватный метод «Letter» — который возращает массив с «box» буквами, их можно взять из моего кода(который ниже), или найти в интернете.

private static string[,] Letter() {   string[,] letter = new string[,]   {     {       //letter with index 0       "    ",       "    ",       "    ",       "    ",       "    ",       "    ",     },     {       //letter with index 1       "╔══╗",       "║╔╗║",       "║╚╝║",       "║╔╗║",       "║║║║",       "╚╝╚╝",     },     {       //letter with index 2       "╔═══╗",       "║╔══╝",       "║╚══╗",       "║╔═╗║",       "║╚═╝║",       "╚═══╝",     },     {       //letter with index 3       "╔══╗ ",       "║╔╗║ ",       "║╚╝╚╗",       "║╔═╗║",       "║╚═╝║",       "╚═══╝",     },     {       //letter with index 4       "╔══╗",       "║╔═╝",       "║║  ",       "║║  ",       "║║  ",       "╚╝  ",     },     {       //letter with index 5       " ╔══╗ ",       " ║╔╗║ ",       " ║║║║ ",       " ║║║║ ",       "╔╝╚╝╚╗",       "╚════╝",     },     {       //letter with index 6       "╔═══╗",       "║╔══╝",       "║╚══╗",       "║╔══╝",       "║╚══╗",       "╚═══╝",     },     {       //letter with index 7       "╔╩═╩╗",       "║╔══╝",       "║╚══╗",       "║╔══╝",       "║╚══╗",       "╚═══╝",     },     {       //letter with index 8       "╔╗╔╗╔╗",       "║║║║║║",       "║╚╝╚╝║",       "║╔╗╔╗║",       "║║║║║║",       "╚╝╚╝╚╝",     },     {       //letter with index 9       "╔═══╗",       "╚══╗║",       " ╔═╝║",       " ╚═╗║",       "╔══╝║",       "╚═══╝",     },     {       //letter with index 10       "╔╗╔╗",       "║║║║",       "║║║║",       "║║╔║",       "║╚╝║",       "╚══╝",     },     {       //letter with index 11       "╔╗╩╔╗",       "║║ ║║",       "║║ ║║",       "║║ ╔║",       "║╚═╝║",       "╚═══╝",     },     {       //letter with index 12       "╔╗╔══╗",       "║║║╔═╝",       "║╚╝║  ",       "║╔╗║  ",       "║║║╚═╗",       "╚╝╚══╝",     },     {       //letter with index 13       " ╔══╗",       " ║╔╗║",       " ║║║║",       " ║║║║",       "╔╝║║║",       "╚═╝╚╝",     },     {       //letter with index 14       "╔╗  ╔╗",       "║║  ║║",       "║╚╗╔╝║",       "║╔╗╔╗║",       "║║╚╝║║",       "╚╝  ╚╝",     },     {       //letter with index 15       "╔╗╔╗",       "║║║║",       "║╚╝║",       "║╔╗║",       "║║║║",       "╚╝╚╝",     },     {       //letter with index 16       "╔══╗",       "║╔╗║",       "║║║║",       "║║║║",       "║╚╝║",       "╚══╝",     },     {       //letter with index 17       "╔══╗",       "║╔╗║",       "║║║║",       "║║║║",       "║║║║",       "╚╝╚╝",     },     {       //letter with index 18       "╔═══╗",       "║╔═╗║",       "║╚═╝║",       "║╔══╝",       "║║   ",       "╚╝   ",     },     {       //letter with index 19       "╔══╗",       "║╔═╝",       "║║  ",       "║║  ",       "║╚═╗",       "╚══╝",     },     {       //letter with index 20       "╔════╗",       "╚═╗╔═╝",       "  ║║  ",       "  ║║  ",       "  ║║  ",       "  ╚╝  ",     },     {       //letter with index 21       "╔╗╔╗",       "║║║║",       "║╚╝║",       "╚═╗║",       " ╔╝║",       " ╚═╝",     },     {       //letter with index 22       "╔═════╗",       "║ ╔╦╗ ║",       "║ ║║║ ║",       "║ ╚╩╝ ║",       "╚═╗ ╔═╝",       "  ╚═╝  ",     },     {       //letter with index 23       "╔══╗╔══╗",       "╚═╗║║╔═╝",       "  ║╚╝║  ",       "  ║╔╗║  ",       "╔═╝║║╚═╗",       "╚══╝╚══╝",     },     {       //letter with index 24       "╔╗╔╗",       "║║║║",       "║║║║",       "║║║║",       "║╚╝║",       "╚══╗",     },     {       //letter with index 25       "╔╗╔╗",       "║║║║",       "║╚╝║",       "╚═╗║",       "  ║║",       "  ╚╝",     },     {       //letter with index 26       "╔╗╔╗╔╗",       "║║║║║║",       "║║║║║║",       "║║║║║║",       "║╚╝╚╝║",       "╚════╝",     },     {       //letter with index 27       "╔╗╔╗╔╗",       "║║║║║║",       "║║║║║║",       "║║║║║║",       "║╚╝╚╝║",       "╚════╗",     },     {       //letter with index 28       "═╗   ",       "╗║   ",       "║╚══╗",       "║╔═╗║",       "║╚═╝║",       "╚═══╝",     },     {       //letter with index 29       "╔╗  ╔╗",       "║║  ║║",       "║╚══╣║",       "║╔═╗║║",       "║╚═╝║║",       "╚═══╩╝",     },     {       //letter with index 30       "╔╗   ",       "║║   ",       "║╚══╗",       "║╔═╗║",       "║╚═╝║",       "╚═══╝",     },     {       //letter with index 31       "╔═══╗",       "╚══╗║",       " ╔═╝╝",       " ╚═╗╗",       "╔══╝║",       "╚═══╝",     },     {       //letter with index 32       "╔╗╔══╗",       "║║║╔╗║",       "║╚╝║║║",       "║╔╗║║║",       "║║║╚╝║",       "╚╝╚══╝",     },     {       //letter with index 33       "╔═══╗",       "║╔═╗║",       "║╚═╝║",       "╚╗╔╗║",       " ║║║║",       " ╚╝╚╝",     },     {       //letter with index 34       " ╔╗",       "╔╝║",       "╚╗║",       " ║║",       " ║║",       " ╚╝",     },     {       //letter with index 35       "╔══╗",       "╚═╗║",       "╔═╝║",       "║╔═╝",       "║╚═╗",       "╚══╝",     },     {       //letter with index 36       "╔══╗",       "╚═╗║",       "╔═╝║",       "╚═╗║",       "╔═╝║",       "╚══╝",     },     {       //letter with index 37       "╔╗╔╗",       "║║║║",       "║╚╝║",       "╚═╗║",       "  ║║",       "  ╚╝",     },     {       //letter with index 38       "╔══╗",       "║╔═╝",       "║╚═╗",       "╚═╗║",       "╔═╝║",       "╚══╝",     },     {       //letter with index 39       "╔══╗",       "║╔═╝",       "║╚═╗",       "║╔╗║",       "║╚╝║",       "╚══╝",     },     {       //letter with index 40       "╔══╗",       "╚═╗║",       "  ║║",       "  ║║",       "  ║║",       "  ╚╝",     },     {       //letter with index 41       "╔══╗",       "║╔╗║",       "║╚╝║",       "║╔╗║",       "║╚╝║",       "╚══╝",     },     {       //letter with index 42       "╔══╗",       "║╔╗║",       "║╚╝║",       "╚═╗║",       "╔═╝║",       "╚══╝",     },     {       //letter with index 43       "╔══╗",       "║╔╗║",       "║║║║",       "║║║║",       "║╚╝║",       "╚══╝",     },     {       //letter with index 44       "  ",       "  ",       "  ",       "  ",       "╔╗",       "╚╣",     },     {       //letter with index 45       "  ",       "  ",       "  ",       "  ",       "╔╗",       "╚╝",     },     {       //letter with index 46       "╔╗",       "║║",       "║║",       "╚╝",       "╔╗",       "╚╝",     },     {       //letter with index 47       "╔═╗",       "╚╗║",       "╔╝║",       "║╔╝",       "╔╗ ",       "╚╝ ",     },     {       //letter with index 48       "  ",       "╔╗",       "╚╝",       "╔╗",       "╚╝",       "  ",     },     {       //letter with index 49       "╔═╗",       "╚╗║",       " ║║",       " ║║",       "╔╝║",       "╚═╝",     },     {       //letter with index 50       "╔═╗",       "║╔╝",       "║║ ",       "║║ ",       "║╚╗",       "╚═╝",     },     {       //letter with index 51       "    ",       "    ",       "╔══╗",       "╚══╝",       "    ",       "    ",     },     {       //letter with index 52       "              ",       " ▄█▀█▄  ▄███▄ ",       "▐█░██████████▌",       " ██▒█████████ ",       "  ▀████████▀  ",       "     ▀██▀     ",     },     {       //letter with index 53       "###",       "@@@",       "###",       "@@@",       "###",       "@@@",     },   };    return letter; }

Завязка

В классе «Print» создаем еще один метод, который будет записывать в массив(буфер) и выводить «box» текст на экран.

public static void Phrase(string phrase) //В МЕТОД ВПИСЫВАЕТ СТРОКА {   //ОБЪЯВЛЯЕМ МАССИВЫ   char[] arrPhrase = phrase.ToCharArray(); //РАЗБИВАЕМ ФРАЗУ НА CHAR ЭЛЕМЕНТЫ   char[] arrSymbol = new char[] { ' ', 'А', 'Б', 'В', 'Г', 'Д', 'Е', 'Ё', 'Ж', 'З', 'И', 'Й', 'К', 'Л', 'М', 'Н', 'О', 'П', 'Р', 'С', 'Т', 'У', 'Ф', 'Х', 'Ц', 'Ч', 'Ш', 'Щ', 'Ъ', 'Ы', 'Ь', 'Э', 'Ю', 'Я', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', ',', '.', '!', '?', ':', ')', '(', '-', '♥' } //СИМВОЛЫ КОТОРЫЕ МЫ БУДЕМ СРАВНИВАТЬ С СИМВОЛОЛАМИ  arrPhrase SE//   string[,] arrLetter = Letter(); //БЕРЕМ МАССИВ С "BOX" БУКВАМИ   string[,] buffer = new string[arrLetter.GetLength(1), arrPhrase.Length]; //БУФЕР КОТОРЫЙ БУДЕТ В СЕБЕ ХРАНИТЬ БУКВЫ, ВЫСОТА У НЕГО ЭТО КОЛ-ВО РЯДКОВ У "BOX" БУКВЫ, У ВСЕХ БУКВ ВЫСОТА 6 РЯДКОВ, А ШИРИНА У НЕГО ЭТО КОЛИЧЕСТВО БУКВ В ФРАЗЕ    //ПОСКОЛЬКУ СИМВОЛОВ ВРЯД-ЛИ БУДЕТ > 255, ТО ДЛЯ ТОГО, ЧТОБ ЭКНОМИТЬ ОЗУ МЫ БУДЕМ БРАТЬ ТИП ДАННЫХ BYTE, ПОЭТОМУ ДЕЛАЛ ПРОВЕРКУ, ЧТОБ ЭЛЕМЕНТОВ НЕ БЫЛО > 255   if (arrPhrase.Length > 255)   {     Console.WriteLine($"ERROR: the number of characters is more than {255}");   }    //ЦИКЛ КОТОРЫЙ ДЕЛАЕТ ПРОВЕРКУ ЭЛЕМЕНТОВ И ЗАПИСЫВАЕТ В БУФЕР ЭЛЕМЕНТЫ   for (byte i = 0; i < arrPhrase.Length; i++) //ТИП BYTE ОПЯТЬ ЖЕ, ЧТОБ ЭКОНОМИТЬ ПАМЯТЬ   { //САМ ЦИКЛ ПРОСТО ПЕРЕБИРАЕТ КАЖДЫЙ CHAR ЭЛЕМЕНТ СТРОКИ, КОТОРУЮ ПИШЕМ В МЕТОД     byte index = 0; //ЭТО НАМ НУЖНО БУДЕТ, ЧТОБ В БУФЕР ЗАПИСАТЬ "BOX" БУКВУ С ОПРЕДЕЛЕННЫМ ИНДЕКСОМ, КАЖДЫЙ ИНДЕКС УКАЗАН В КОММЕНТАРИЯХ В САМОМ МАССИВЕ С ЭТИМИ БУКВАМИ, ЧТОБ НЕ ЗАПУТАТЬСЯ      for (byte k = 0; k < arrSymbol.Length; k++) //ТУТ МЫ ПРОСТО ПЕРЕБИРАЕМ КАЖДЫЙ ЭЛЕМЕНТ ИЗ МАССИВА С СИМВОЛАМИ КОТОРЫЙ МЫ ПИСАЛИ РАНЕЕ     {       if (arrPhrase[i] == arrSymbol[k]) { index = k; break; } //СРАВНИВАЕМ CHAR ЭЛЕМЕНТ СТРОКИ С CHAR ЭЛЕМЕНТОМ МАССИВА С СИМВОЛАМИ, ЕСЛИ СОВПАЛО, ТО МЫ НАЗНАЧАЕМ НУЖНЫЙ ИНДЕКС И ВЫХОДИМ ИЗ ЦИКЛА, ДАБЫ ДАЛЬШЕ НЕ ТРАТИТЬ РЕСУРСЫ ПК НА ПРОВЕРКУ       else index = 53; //ЕСЛИ НЕ БЫЛО СОВПАДЕНИЯ, ТО МЫ НАЗНАЧЕМ INDEX, КОТОРЫЙ СООТВЕТВУЕТ "BOX" БУКВЕ С # И @ (ТИП ОШИБКА)     }      //ЗАПИСЫВАЕМ В БУФЕР "BOX" БУКВЫ     for (byte j = 0; j < arrLetter.GetLength(1); j++)     {       buffer[j, i] = arrLetter[index, j]; //ЗАПИСУЕМ ПО-СТРОЧНО БУКВЫ В БУФФЕР     }   }    //ВЫВОД МАССИВА   for (byte i = 0; i < arrLetter.GetLength(1); i++) //ВЫСОТА БУФЕРА ЭТО КОЛ-ВО РЯДКОВ В БУКВЕ   {     for (byte j = 0; j < arrPhrase.Length; j++) //ШИРИНА БУФЕРА КОЛ-ВО БУКВ В ФРАЗЕ     {       Console.Write(buffer[i, j]);     }     Console.WriteLine();   } }

Развитие действия

Дабы сделать «анимацию» нам просто надо стирать предыдущую строку с задержкой, чтоб вывелась новая. Для этого опять таки в классе «Print» создаем метод «Clear», который с задержкой стирает консоль.

public static void Clear(double second) {   Thread.Sleep(TimeSpan.FromSeconds(second)); //ПК "СПИТ" НАЗНАЧЕННОЕ КОЛ-ВО СЕКУНД   Console.Clear(); //ОЧИЩЕНИЕ КОНСОЛИ }

СЕЙЧАС СТРУКТУРА КЛАССА «PRINT» ВЫГЛЯДИТ ТАК:

Кульминация

Пробуем в Main вывести наше чудо.
Делаем простенький цикл, который будет работать как секундомер

Нажимаем f5 и скрещиваем пальчики)

не успел запись включить, но все работает
не успел запись включить, но все работает

Развязка

Теперь, пишем вывод, который был на гифке в начале моего поста

Print.Phrase("ПРИВЕТ, ХАБР"); Print.Clear(1.5); Print.Phrase("КАК"); Thread.Sleep(TimeSpan.FromSeconds(.5)); Print.Phrase("У ТЕБЯ"); Thread.Sleep(TimeSpan.FromSeconds(.5)); Print.Phrase("ДЕЛА?"); Print.Clear(2); Print.Phrase("У МЕНЯ ХОРОШО"); Print.Phrase(":)"); Print.Clear(1.5); Print.Phrase("СПАСИБО"); Print.Clear(.5); Print.Phrase("ВАМ"); Print.Clear(.5); Print.Phrase("ЗА"); Print.Clear(.5); Print.Phrase("АКТИВНОСТЬ"); Print.Clear(1.5); Print.Phrase("ЛЮБЛЮ ВАС"); Print.Clear(1.5); Console.ForegroundColor = ConsoleColor.Red; Print.Phrase("♥"); Print.Clear(1.5);

Эпилог

Достаточно простенькое, но забавное приложение, которое скорее всего соберет меньше просмотров чем предыдущее сердечко, но над этим постом я старался больше). В любом случае спасибо всем кто просмотрит и прокомментирует, а тем более если найдут ошибки, или облегчат/улучшат код.


ссылка на оригинал статьи https://habr.com/ru/articles/586830/