Пролог
Прошлый пост на счет сердечка посмотрело много людей и у меня возникла идея сделать еще одну простенькую, но достаточно красивую штуку, а именно такой вот вывод текста(можно сказать анимированного, но язык не поворачивается). Данный пост подходит для новичков, можно потренироваться в использовании массивов, циклов, немного классов и методов.
Экспозиция
Создаем класс "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);
Эпилог
Достаточно простенькое, но забавное приложение, которое скорее всего соберет меньше просмотров чем предыдущее сердечко, но над этим постом я старался больше). В любом случае спасибо всем кто просмотрит и прокомментирует, а тем более если найдут ошибки, или облегчат/улучшат код.
Комментарии (4)
WhiteBlackGoose
02.11.2021 11:45Автор, вы бы хотя бы дали кому-нибудь свой код на ревью.
Кстати, вот [эта](https://github.com/spectreconsole/spectre.console) либа позволяет это делать очень недурно.
LoadRunner
Уж лучше в словарь пихать Box-буквы, в качестве ключа брать код ASCII этого символа.
И в качестве улучшения - лучше не хардкодить выводимый текст, а предусмотреть загрузку из внешних источников. Из текстового файла, например.
Frog_cry_too Автор
Хорошая идея, сяб)