Reputation: 21
Code
namespace testasciiart
{
class MainClass
{
public static string a()
{
string astring = String.Empty;
string[] aarray =
{
"_____ ",
"\\__ \\ ",
" / __ \\_",
"(____ /",
" \\/ "
};
for (int i = 0; i < aarray.Length; i++)
{
astring += aarray[i] + "\n";
};
return astring;
}
public static string b()
{
string bstring = String.Empty;
string[] barray =
{
"___. ",
"\\_ |__ ",
" | __ \\ ",
" | \\_\\ \\",
" |___ /",
" \\/ "
};
for (int i = 0; i < barray.Length; i++)
{
bstring += barray[i] + "\n";
}
return bstring;
}
public static void Main(string[] args)
{
Console.WriteLine(a() + b());
}
}
}
my problem is when i try to do:
Console.WriteLine(a() + b());
it comes out like the image below rather than printing the second letter after the first letter, on the same line.
how can i fix this?
Upvotes: 2
Views: 760
Reputation: 81523
The problem is you need to join the letter at the array level. I.e Each array has several lines for the character, you need to join each of the lines. It makes sense really
The advantage is you give it text, you can set up different font libraries
public interface IFont
{
Dictionary<char, Func<string[]>> Mapping { get; }
}
public class MyFont : IFont
{
public static string[] b = {
"___. ",
"\\_ |__ ",
" | __ \\ ",
" | \\_\\ \\",
" |___ /",
" \\/ "};
public static string[] a = {
"_____ ",
"\\__ \\ ",
" / __ \\_",
"(____ /",
" \\/ "};
public Dictionary<char, Func<string[]>> Mapping { get; }
= new Dictionary<char, Func<string[]>>{
{ 'b', () => b},
{ 'a', () => a}};
}
Generic Join
public static string JoinLetters<T>(int space, string text)
where T : class, IFont, new()
{
var font = new T();
// get the letters
var arrays = text.ToCharArray()
.Where(x => font.Mapping.ContainsKey(x))
.Select(x => font.Mapping[x].Invoke())
.ToList();
// get the max height and width
var h = arrays.Max(x => x.Length);
var w = arrays.Max(x => x.Max(y => y.Length)) + space;
var result = new string[h];
// join each letter
// if the letter is too short, add default width
foreach (var array in arrays)
for (var j = 0; j < h; j++)
result[j] += (j >= array.Length ? " " : array[j]).PadRight(w);
return string.Join(Environment.NewLine, result);
}
Usage
static void Main()
{
Console.WriteLine(JoinLetters<MyFont>(2, "abba"));
}
Output
_____ ___. ___. _____
\__ \ \_ |__ \_ |__ \__ \
/ __ \_ | __ \ | __ \ / __ \_
(____ / | \_\ \ | \_\ \ (____ /
\/ |___ / |___ / \/
\/ \/
A simple solution might be to describe your letters like this
public static string[] b()
{
string[] barray =
{
"___. ",
"\\_ |__ ",
" | __ \\ ",
" | \\_\\ \\",
" |___ /",
" \\/ "
};
return barray;
}
Use a join method
public static string JoinLetters(int space, params Func<string[]>[] args)
{
// get the letters
var arrays = args.Select(x => x.Invoke()).ToList();
// get the max height
var h = arrays.Max(x => x.Length);
// get the max letter width
var w = arrays.Max(x => x.Max(y => y.Length));
var result = new string[h];
// join each letter
foreach (var array in arrays)
for (var j = 0; j < h; j++)
{
// Add padding space
result[j] += new string(' ', space);
// if the letter is too short, add default width
if (j >= array.Length)
result[j] += new string(' ', w);
else
result[j] += array[j].PadRight(w);
}
return string.Join(Environment.NewLine, result);
}
Usasge
public static void Main(string[] args)
{
// note, the 2 is just a space between letters
Console.WriteLine(JoinLetters(2, a, b, b, a));
}
Add pepper and salt to taste
Output
_____ ___. ___. _____
\__ \ \_ |__ \_ |__ \__ \
/ __ \_ | __ \ | __ \ / __ \_
(____ / | \_\ \ | \_\ \ (____ /
\/ |___ / |___ / \/
\/ \/
Upvotes: 4
Reputation: 37050
Another alternative would be to manually set the cursor position in the console window each time you write a letter, which allows you to do other operations between writing letters, and still have them "joined" on the same line as you write them.
To begin with, let's make your letter arrays constants:
private static readonly string[] A =
{
"_____ ",
"\\__ \\ ",
" / __ \\_",
"(____ /",
" \\/ "
};
private static readonly string[] B =
{
"___. ",
"\\_ |__ ",
" | __ \\ ",
" | \\_\\ \\",
" |___ /",
" \\/ "
};
Now what we can do is write a method that draws a letter by writing each line of the array, but manually setting the cursor position to the next line (but at the same starting column) each time.
To do this, we can capture the initial values for the cursor, as well as the width of the longest line (so we can manually set the cursor at the end of the letter when we're done). Then, for each line, we just write the line, increment the top (which moves the cursor down), and set the cursor back to the starting "left" position.
At the end, we move the cursor back to the original top, and one space to the right of our longest line:
private static void DrawLetter(string[] letter)
{
var top = Console.CursorTop;
var left = Console.CursorLeft;
var width = letter.Max(line => line.Length);
foreach (var line in letter)
{
Console.Write(line);
Console.SetCursorPosition(left, ++Console.CursorTop); // <- Increment top here
}
Console.SetCursorPosition(left + width + 1, top);
}
One other thing we may need is a method that sets our cursor at the next line. To do this, I've hard-coded 7
as the max rows a letter would have, plus one, and then set the cursor position down that many rows, and to the first column (0
):
private static void DrawNewLine()
{
Console.SetCursorPosition(0, 7);
}
Now we can write our letters like:
static void Main()
{
DrawLetter(A);
DrawLetter(B);
DrawLetter(B);
DrawLetter(A);
DrawNewLine();
GetKeyFromUser("\nPress any key to exit...");
}
Output
Now if we want to be fancy, we can write another method that takes a params
argument (which allows a variable number of arguments to be sent to a method), which will write out many letters at once (calling our helper method above):
private static void DrawLetters(params string[][] letters)
{
foreach (var letter in letters)
{
DrawLetter(letter);
}
}
Using this method, our code above can now be replaced with:
static void Main()
{
DrawLetters(A, B, B, A);
DrawNewLine();
GetKeyFromUser("\nPress any key to exit...");
}
Upvotes: 0