在C#控制台应用程序中打印ASCII线艺术字符

18

我想要一个C#控制台应用程序打印扩展ASCII码,来自http://www.asciitable.com/。 特别是我想看看线条艺术字符:169、170、179-218。不幸的是,当我尝试时,我得到了218的 'Ú' 字符,并期望在http://www.csharp411.com/ascii-table/中看到其他字符。

我知道ASCII仅指定字符代码0-127。 我找到了另一篇帖子,涉及SetConsoleOutputCP(),但无法在C#类中使用它,也找不到如何执行此操作的示例。

是否可能在C#控制台应用程序中打印线条艺术字符? 如果可以,有人能够提供一个URL示例或代码吗?

5个回答

25

一个小程序,可以修改Console.OutputEncoding属性使用你所需的字符编码:

class Program
{
    static void Main(string[] args)
    {
        Console.OutputEncoding = System.Text.Encoding.GetEncoding(1252);
        Console.WriteLine((char) 169);
        Console.WriteLine((char) 170);

        for(char c = (char)179; c <= (char)218; ++c)
        {
            Console.WriteLine(c);
        }
    }
}

编辑:

因此,我已经查找了盒装图案的Unicode等效字符。有一些额外的字形可能对您有用。那个维基百科页面列出了它们所有的代码点。

我组合了这个来尝试它们:

class Program
{
    static void Main(string[] args)
    {
        for(int i = 0x2500; i <= 0x2570; i += 0x10)
        {
            for(int c = 0; c <= 0xF; ++c)
            {
                Console.Write((char) (i + c));
            }

            Console.WriteLine();
        }
    }
}

对我来说, 很多字符只显示为?, 但是那些我们在旧ASCII游戏中常见的标准方块字形是可以正常显示的。希望这些对你有用。


我尝试了437,但对我没用。代码页1252产生了他在示例中使用的所需扩展ASCII字符。 - Joshua Rodgers
这似乎提供了一个更改输出编码的示例。不幸的是,我得到的是原始输出而不是线条艺术。@Ron 我也尝试了437并且有相同的结果。 - Demitrius Nelon
@Joshua 感谢您的反馈。我在使用美国版的Windows XP Professional Version 2002 Service Pack 3进行本地开发,而在部署时则使用Windows Server 2008。我将在其中一台远程服务器上测试代码。 - Demitrius Nelon
@Joshua 它在我的远程服务器2008上运行良好,所以我将标记它为已回答。我将继续查看我本地的XP环境,看看是什么原因导致不兼容。 - Demitrius Nelon
我已更新答案,包括Unicode等效信息。希望这些在更多环境中能够起作用。 - Joshua Rodgers
显示剩余2条评论

5
为了在控制台上查看正确的ASCII,我只需要做这个:
Console.OutputEncoding = System.Text.Encoding.GetEncoding(28591);
为了理解ASCII表,我编写了下面的代码:
using System;

namespace AsciiChart
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.OutputEncoding = System.Text.Encoding.GetEncoding(28591);
            for (int i = 0; i < 256; i++) {
               Console.Write(i+"=> ["+(char)i +"]  \n");
            }
            Console.ReadKey();
        }
    }
}

在此输入图片描述

开始绘制,示例1:

using System;

namespace AsciiBorder
{
    class Program
    {
        static void Main(string[] args)
        {
            int topleft = 218;
            int hline = 196;
            int topright = 191;
            int vline = 179;
            int bottomleft = 192;
            int bottomright = 217;

            Console.OutputEncoding = System.Text.Encoding.GetEncoding(28591);
            //draw top left corner
            Write(topleft);
            //draw top horizontal line
            for (int i = 0; i < 10; i++)
                Write(hline);
            //draw top right corner
            Write(topright);
            Console.WriteLine();
            //draw left and right vertical lines
            for (int i = 0; i < 6; i++)
            {
                Write(vline);
                for (int k = 0; k < 10; k++) {
                    Console.Write(" ");
                }
                WriteLine(vline);
            }
            //draw bottom left coner
            Write(bottomleft);
            //draw bottom horizontal line
            for (int i = 0; i < 10; i++)
                Write(hline);
            //draw bottom right coner
            Write(bottomright);
            Console.ReadKey();
        }
        static void Write(int charcode)
        {
            Console.Write((char)charcode);
        }
        static void WriteLine(int charcode)
        {
            Console.WriteLine((char)charcode);
        }
    }
}

控制台输出:

输入图像描述

有关 Latin 1 和 ASCII 代码页的更多信息

完成的3x3井字棋式的画板绘制代码:示例2

输入图像描述

代码:

using System;

namespace AsciiBorder
{
    class Program
    {
        const int topleft = 218, hline = 196, topright = 191, vline = 179, bottomleft = 192, bottomright = 217, cross = 197, topT = 194, bottomT = 193, leftT = 195, rightT = 180;
        const int space = 10/*this determine size of the single cell*/, spacer_ex = (space / 2) + 1;
        static void Main(string[] args)
        {            
            Console.OutputEncoding = System.Text.Encoding.GetEncoding(28591);
            Console.Title = "3x3 Board";
            DrawTop();
            DrawMidSpacer();
            DrawMiddle();
            DrawMidSpacer();
            DrawMiddle();
            DrawMidSpacer();
            DrawBottom();

            Console.ReadKey();
        }
        static void DrawBottom() {
            #region bottom
            Write(bottomleft);
            for (int i = 0; i < space; i++)
                Write(hline);
            Write(bottomT);
            for (int i = 0; i < space; i++)
                Write(hline);
            Write(bottomT);
            for (int i = 0; i < space; i++)
                Write(hline);
            Write(bottomright);

            Console.WriteLine();
            #endregion
        }
        static void DrawMiddle() {
            #region middle
            Write(leftT);
            for (int i = 0; i < space; i++)
                Write(hline);
            Write(cross);
            for (int i = 0; i < space; i++)
                Write(hline);
            Write(cross);
            for (int i = 0; i < space; i++)
                Write(hline);
            Write(rightT);

            Console.WriteLine();
            #endregion
        }
        static void DrawMidSpacer() {
            #region middlespacer
            for (int x = 0; x < spacer_ex; x++)
            {
                Write(vline);
                for (int i = 0; i < space; i++)
                    Console.Write(" ");
                Write(vline);
                for (int i = 0; i < space; i++)
                    Console.Write(" ");
                Write(vline);
                for (int i = 0; i < space; i++)
                    Console.Write(" ");
                Write(vline);

                Console.WriteLine();
            }
            #endregion
        }
        static void DrawTop() {
            #region top
            Write(topleft);
            for (int i = 0; i < space; i++)
                Write(hline);
            Write(topT);
            for (int i = 0; i < space; i++)
                Write(hline);
            Write(topT);
            for (int i = 0; i < space; i++)
                Write(hline);
            Write(topright);

            Console.WriteLine();
            #endregion
        }
        static void Write(int charcode)
        {
            Console.Write((char)charcode);
        }
        static void WriteLine(int charcode)
        {
            Console.WriteLine((char)charcode);
        }
    }
}

2

您可以在Windows中直接使用ASCII表中的符号。

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("╔═╗");
        Console.WriteLine("╚═╝");
    }
}

这确实有效(至少在我使用的美国Windows 7上的PowerShell控制台中)。有趣的是,只有在使用Console.Write / Writeline方法时才能正常工作。如果我执行Console.OpenStandardOutput(),然后使用生成的流来写入文本,它会输出乱码。我尝试了几种变化,包括在OpeningStandardOutput之前将OutputEncoding更改为1252,以及构建一个具有1252编码的StreamWriter,用于写入stdout流。没有成功。我想知道Console.WriteLine有什么不同。 - Simon Gillbee
如果使用StreamWriter,请尝试使用CP850。 - user2084865

1

我曾经为此战斗了好几天。我认为无论其他人怎么说,都不可能做到。现在,我正在尝试制作矮人要塞风格的游戏。如果你也在做同样的事情,请像他一样使用图像。

  • 更快,因为它可以利用图形加速。
  • 更容易,因为它们是瓷砖,并且有很多关于如何处理它们的教程。
  • 得到良好支持,例如XNA,已经成为你正在使用的框架。
  • 可扩展,因此您可以在以后的日期中替换其他图像,例如DF中的胡须笑容。

这不是为了游戏 :( 这是一个商业应用程序,因此我需要能够在控制台窗口中看到结果,并希望能够获得类似于日志记录/审核的输出文件。 - Demitrius Nelon
1
很酷。我回答这个问题不是为了你,而是为了可能会遇到这个问题的其他人。 - DampeS8N

0

我不知道如何让ASCII工作,但如果你想要的话,可以使用Unicode到某种程度。这需要将控制台设置为真正的字体。

Michael Kaplan的文章“任何说控制台不能做Unicode的人都没有他们想象中聪明”包括此代码。

我无法直接运行他的代码,但只要我从True Type Font Console中运行它,它就对我起作用了。该文章包括如何设置它。

using System;
using System.Runtime.InteropServices;
namespace TestUnicode

{
    class Program
{



public static void Main(string[] args) {
    string st = "\u0169\u0129\n\n";
    IntPtr stdout = GetStdHandle(STD_OUTPUT_HANDLE);
    uint written;
    WriteConsoleW(stdout, st, st.Length, out written, IntPtr.Zero);
}


[DllImport("kernel32.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
internal static extern bool WriteConsoleW(IntPtr hConsoleOutput,
                                          string lpBuffer,
                                          int nNumberOfCharsToWrite,
                                          out uint lpNumberOfCharsWritten,
                                          IntPtr lpReserved);


internal static bool IsConsoleFontTrueType(IntPtr std) {
 CONSOLE_FONT_INFO_EX cfie = new CONSOLE_FONT_INFO_EX();
    cfie.cbSize = (uint)Marshal.SizeOf(cfie);
    if(GetCurrentConsoleFont(std, false, ref cfie)) {
        return(((cfie.FontFamily & TMPF_TRUETYPE) == TMPF_TRUETYPE));
    }
    return false;
}



[DllImport("Kernel32.DLL", ExactSpelling = true)]
internal static extern IntPtr GetStdHandle(int nStdHandle);


[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
internal static extern bool GetCurrentConsoleFont(IntPtr hConsoleOutput,
                                                    bool bMaximumWindow, 
                                                    ref CONSOLE_FONT_INFO_EX lpConsoleCurrentFontEx);



internal struct COORD {
    internal short X;
    internal short Y;
    internal COORD(short x, short y) {
        X = x;
        Y = y;
    }
}

[StructLayout(LayoutKind.Sequential)]
internal unsafe struct CONSOLE_FONT_INFO_EX {
    internal uint cbSize;
    internal uint nFont;
    internal COORD dwFontSize;
    internal int FontFamily;
    internal int FontWeight;
    fixed char FaceName[LF_FACESIZE];
}

internal const int TMPF_TRUETYPE = 0x4;
internal const int LF_FACESIZE = 32;
internal const string BOM = "\uFEFF";
internal const int STD_OUTPUT_HANDLE = -11; // Handle to the standard output device.
internal const int ERROR_INVALID_HANDLE = 6;
internal const int ERROR_SUCCESS = 0;
internal const uint FILE_TYPE_UNKNOWN = 0x0000;
internal const uint FILE_TYPE_DISK = 0x0001;
internal const uint FILE_TYPE_CHAR = 0x0002;
internal const uint FILE_TYPE_PIPE = 0x0003;
internal const uint FILE_TYPE_REMOTE = 0x8000;
internal static IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);
}
    }

我正在使用VS 2010,并且出现了一个错误:“如果使用/unsafe编译,不安全的代码才能出现。”我得查一下这个。 - Demitrius Nelon
好的,在将项目属性更改为允许不安全代码后,我成功运行了该项目,但仍然不确定是否看到了我要找的东西。 - Demitrius Nelon
你需要从设置为True Type字体的控制台中运行它,因此直接从VS运行项目是行不通的。我链接的文章描述了如何设置字体。 - Conrad Frix
我的控制台字体默认为Lucida Console。我确实看了那篇文章,但没有构建和运行。我会尝试一下...不幸的是,我得到了与之前相同的结果。这可能与我的环境有关。 - Demitrius Nelon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接