using System; using System.Collections.Generic; using System.Linq; namespace banner { class Banner { private int Horizontal { get; set; } private int Vertical { get; set; } private bool Centered { get; set; } private string Character { get; set; } private string Statement { get; set; } // This provides a bit-ended representation of each symbol // that can be output. Each symbol is defined by 7 parts - // where each part is an integer value that, when converted to // the binary representation, shows which section is filled in // with values and which are spaces. i.e., the 'filled in' // parts represent the actual symbol on the paper. Dictionary letters = new Dictionary() { {' ', new int[] { 0, 0, 0, 0, 0, 0, 0 } }, {'A', new int[] {505, 37, 35, 34, 35, 37, 505} }, {'B', new int[] {512, 274, 274, 274, 274, 274, 239} }, {'C', new int[] {125, 131, 258, 258, 258, 131, 69} }, {'D', new int[] {512, 258, 258, 258, 258, 131, 125} }, {'E', new int[] {512, 274, 274, 274, 274, 258, 258} }, {'F', new int[] {512, 18, 18, 18, 18, 2, 2} }, {'G', new int[] {125, 131, 258, 258, 290, 163, 101} }, {'H', new int[] {512, 17, 17, 17, 17, 17, 512} }, {'I', new int[] {258, 258, 258, 512, 258, 258, 258} }, {'J', new int[] {65, 129, 257, 257, 257, 129, 128} }, {'K', new int[] {512, 17, 17, 41, 69, 131, 258} }, {'L', new int[] {512, 257, 257, 257, 257, 257, 257} }, {'M', new int[] {512, 7, 13, 25, 13, 7, 512} }, {'N', new int[] {512, 7, 9, 17, 33, 193, 512} }, {'O', new int[] {125, 131, 258, 258, 258, 131, 125} }, {'P', new int[] {512, 18, 18, 18, 18, 18, 15} }, {'Q', new int[] {125, 131, 258, 258, 322, 131, 381} }, {'R', new int[] {512, 18, 18, 50, 82, 146, 271} }, {'S', new int[] {69, 139, 274, 274, 274, 163, 69} }, {'T', new int[] {2, 2, 2, 512, 2, 2, 2} }, {'U', new int[] {128, 129, 257, 257, 257, 129, 128} }, {'V', new int[] {64, 65, 129, 257, 129, 65, 64} }, {'W', new int[] {256, 257, 129, 65, 129, 257, 256} }, {'X', new int[] {388, 69, 41, 17, 41, 69, 388} }, {'Y', new int[] {8, 9, 17, 481, 17, 9, 8} }, {'Z', new int[] {386, 322, 290, 274, 266, 262, 260} }, {'0', new int[] {57, 69, 131, 258, 131, 69, 57} }, {'1', new int[] {0, 0, 261, 259, 512, 257, 257} }, {'2', new int[] {261, 387, 322, 290, 274, 267, 261} }, {'3', new int[] {66, 130, 258, 274, 266, 150, 100} }, {'4', new int[] {33, 49, 41, 37, 35, 512, 33} }, {'5', new int[] {160, 274, 274, 274, 274, 274, 226} }, {'6', new int[] {194, 291, 293, 297, 305, 289, 193} }, {'7', new int[] {258, 130, 66, 34, 18, 10, 8} }, {'8', new int[] {69, 171, 274, 274, 274, 171, 69} }, {'9', new int[] {263, 138, 74, 42, 26, 10, 7} }, {'?', new int[] {5, 3, 2, 354, 18, 11, 5} }, {'*', new int[] {69, 41, 17, 512, 17, 41, 69} }, {'=', new int[] {41, 41, 41, 41, 41, 41, 41} }, {'!', new int[] {1, 1, 1, 384, 1, 1, 1} }, {'.', new int[] {1, 1, 129, 449, 129, 1, 1} } }; /// /// This displays the provided text on the screen and then waits for the user /// to enter a integer value greater than 0. /// /// Text to display on the screen asking for the input /// The integer value entered by the user private int GetNumber(string DisplayText) { Console.Write(DisplayText); string TempStr = Console.ReadLine(); Int32.TryParse(TempStr, out int TempInt); if (TempInt <= 0) { throw new ArgumentException($"{DisplayText} must be greater than zero"); } return TempInt; } /// /// This displays the provided text on the screen and then waits for the user /// to enter a Y or N. It cheats by just looking for a 'y' and returning that /// as true. Anything else that the user enters is returned as false. /// /// Text to display on the screen asking for the input /// Returns true or false private bool GetBool(string DisplayText) { Console.Write(DisplayText); return (Console.ReadLine().StartsWith("y", StringComparison.InvariantCultureIgnoreCase)); } /// /// This displays the provided text on the screen and then waits for the user /// to enter an arbitrary string. That string is then returned 'as-is'. /// /// Text to display on the screen asking for the input /// The string entered by the user. private string GetString(string DisplayText) { Console.Write(DisplayText); return (Console.ReadLine().ToUpper()); } /// /// This queries the user for the various inputs needed by the program. /// private void GetInput() { Horizontal = GetNumber("Horizontal "); Vertical = GetNumber("Vertical "); Centered = GetBool("Centered "); Character = GetString("Character (type 'ALL' if you want character being printed) "); Statement = GetString("Statement "); // We don't care about what the user enters here. This is just telling them // to set the page in the printer. _ = GetString("Set page "); } /// /// This prints out a single character of the banner - adding /// a few blanks lines as a spacer between characters. /// private void PrintChar(char ch) { // In the trivial case (a space character), just print out the spaces if (ch.Equals(' ')) { Console.WriteLine(new string('\n', 7 * Horizontal)); return; } // If a specific character to be printed was provided by the user, // then user that as our ouput character - otherwise take the // current character char outCh = Character == "ALL" ? ch : Character[0]; int[] letter = new int[7]; try { letters[outCh].CopyTo(letter, 0); } catch (KeyNotFoundException) { throw new KeyNotFoundException($"The provided letter {outCh} was not found in the letters list"); } // This iterates through each of the parts that make up // each letter. Each part represents 1 * Horizontal lines // of actual output. for (int idx = 0; idx < 7; idx++) { // New int array declarations default to zeros // numSections decides how many 'sections' need to be printed // for a given line of each character int[] numSections = new int[7]; // fillInSection decides whether each 'section' of the // character gets filled in with the character or with blanks int[] fillInSection = new int[9]; // This uses the value in each part to decide which // sections are empty spaces in the letter or filled in // spaces. For each section marked with 1 in fillInSection, // that will correspond to 1 * Vertical characters actually // being output. for (int exp = 8; exp >= 0; exp--) { if (Math.Pow(2, exp) < letter[idx]) { fillInSection[8 - exp] = 1; letter[idx] -= (int)Math.Pow(2, exp); if (letter[idx] == 1) { // Once we've exhausted all of the sections // defined in this part of the letter, then // we marked that number and break out of this // for loop. numSections[idx] = 8 - exp; break; } } } // Now that we know which sections of this part of the letter // are filled in or spaces, we can actually create the string // to print out. string lineStr = ""; if (Centered) lineStr += new string(' ', (int)(63 - 4.5 * Vertical) * 1 / 1 + 1); for (int idx2 = 0; idx2 <= numSections[idx]; idx2++) { lineStr = lineStr + new string(fillInSection[idx2] == 0 ? ' ' : outCh, Vertical); } // Then we print that string out 1 * Horizontal number of times for (int lineidx = 1; lineidx <= Horizontal; lineidx++) { Console.WriteLine(lineStr); } } // Finally, add a little spacer after each character for readability. Console.WriteLine(new string('\n', 2 * Horizontal - 1)); } /// /// This prints the entire banner based in the parameters /// the user provided. /// private void PrintBanner() { // Iterate through each character in the statement foreach (char ch in Statement) { PrintChar(ch); } // In the original version, it would print an additional 75 blank // lines in order to feed the printer paper...don't really need this // since we're not actually printing. // Console.WriteLine(new string('\n', 75)); } /// /// Main entry point into the banner class and handles the main loop. /// public void Play() { GetInput(); PrintBanner(); } } class Program { static void Main(string[] args) { new Banner().Play(); } } }