在C#中显示ASCII艺术字母时出现问题

时间:2018-09-25 06:36:58

标签: c#

代码

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());
        }
    }
}

我的问题是我何时尝试做:

Console.WriteLine(a() + b()); 

它像下面的图片一样出现,而不是在同一行上打印第一个字母之后的第二个字母。

enter image description here

我该如何解决?

2 个答案:

答案 0 :(得分:4)

问题是您需要在数组级别加入字母。即每个数组都有几行用于字符,您需要连接每一行。真的有道理

更新方法

优点是您给它文本,可以设置不同的字体库

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}};     
}

通用联接

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);
}

用法

static void Main()
{
   Console.WriteLine(JoinLetters<MyFont>(2, "abba"));
}

输出

  _____     ___.      ___.      _____   
  \__  \    \_ |__    \_ |__    \__  \  
   / __ \_   | __ \    | __ \    / __ \_
  (____  /   | \_\ \   | \_\ \  (____  /
       \/    |___  /   |___  /       \/ 
                 \/        \/

原始方法

一个简单的解决方案可能是像这样描述您的字母

public static string[] b()
{
   string[] barray =
      {
         "___.    ",
         "\\_ |__  ",
         " | __ \\ ",
         " | \\_\\ \\",
         " |___  /",
         "     \\/ "
      };
   return barray;
}

使用联接方法

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);
}

使用

public static void Main(string[] args)
{
   // note, the 2 is just a space between letters
   Console.WriteLine(JoinLetters(2, a, b, b, a));
}

加入胡椒粉和盐调味

输出

  _____     ___.      ___.      _____   
  \__  \    \_ |__    \_ |__    \__  \  
   / __ \_   | __ \    | __ \    / __ \_
  (____  /   | \_\ \   | \_\ \  (____  /
       \/    |___  /   |___  /       \/ 
                 \/        \/

Full Demo Here

答案 1 :(得分:0)

另一种替代方法是每次写字母时在控制台窗口中手动设置光标位置,这使您可以在写字母之间进行其他操作,并且在写字母时仍将它们“连接”在同一行上

首先,让我们将字母数组设为常量:

private static readonly string[] A =
{
    "_____   ",
    "\\__  \\  ",
    " / __ \\_",
    "(____  /",
    "     \\/ "
};

private static readonly string[] B =
{
    "___.    ",
    "\\_ |__  ",
    " | __ \\ ",
    " | \\_\\ \\",
    " |___  /",
    "     \\/ "
};

现在我们可以做的是编写一种方法,该方法通过写入数组的每一行来绘制字母,但是每次都将光标位置手动设置为下一行(但在同一起始列)。

为此,我们可以捕获光标的初始值以及最长行的宽度(因此,完成后我们可以手动将光标设置在字母的末尾)。然后,对于每行,我们只写一行,增加顶部(将光标向下移动),然后将光标设置回到起始的“左侧”位置。

最后,我们将光标移回原始顶部,并在最长的行的右侧移动一个空格:

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);
}

我们可能需要做的另一件事是将光标设置在下一行的方法。为此,我已经将7硬编码为一个字母所能容纳的最大行数,再加上一个,然后将光标位置设置在这么多行的下方,并设置到第一列(0) :

private static void DrawNewLine()
{
    Console.SetCursorPosition(0, 7);
}

现在我们可以像这样写信了

static void Main()
{
    DrawLetter(A);
    DrawLetter(B);
    DrawLetter(B);
    DrawLetter(A);

    DrawNewLine();

    GetKeyFromUser("\nPress any key to exit...");
}

输出

enter image description here

现在,如果我们想花哨的话,我们可以编写另一个带有params自变量的方法(该方法允许将可变数量的自变量发送到一个方法),该方法可以一次写出许多字母(调用上面的帮助方法):

private static void DrawLetters(params string[][] letters)
{
    foreach (var letter in letters)
    {
        DrawLetter(letter);
    }
}

使用此方法,我们上面的代码现在可以替换为:

static void Main()
{
    DrawLetters(A, B, B, A);

    DrawNewLine();

    GetKeyFromUser("\nPress any key to exit...");
}