【问题标题】:C# How to use Statements in strings to parse textC#如何使用字符串中的语句来解析文本
【发布时间】:2015-01-17 19:43:29
【问题描述】:

我从事基于文本的游戏已经有一段时间了,我遇到的一个问题是当我必须根据可能在整个游戏中发生变化的变量来编写不同的段落时。

我四处寻找解析器等,但大多是找到正则表达式,我认为这在这里没有用。我正在寻找的是某种方式来查看这样的字符串。

String x = "'It's nice to meet you [if (Female){ "Miss, what's a pretty young thing like you doing out in the dessert."} else { "Sir, what can I do for ya?"}]' the man asks in a drawl.";

我目前必须编写用 if 语句分隔的段落,但编写时间要长得多,而且让我更难以保持对话流畅。我的目标是创建一个类,我可以将字符串发送到并在执行时根据整个游戏中变化的变量取回格式化版本。

【问题讨论】:

    标签: c# regex parsing


    【解决方案1】:

    有几种方法可以实现您想要的,但这里是一种方法。有一个根据性别为每个对话生成响应的类:

    class CharacterResponses
    {
        private bool _isFemale;
    
        new CharacterResponses(bool isFemale)
        {
            _isFemale = isFemale;
        }
    
        public string GetResponse1()
        {
            return _isFemale
                ? "Miss, what's a pretty young thing like you doing out in the dessert."
                : "Sir, what can I do for ya?";
        }
    
        public string GetResponse2() // For a different conversation.
        // etc...
    }
    

    现在在你的程序中,你可以有这样的流程:

    var character = new CharacterResponses(true); // Female.
    var x = string.Format("It's nice to meet you {0} the man asks in a drawl.", character.GetResponse1());
    

    这会将特定于角色性别的所有if - then 逻辑保留在其自己的代码块中,并允许您轻松地在主要对话中放置占位符。

    【讨论】:

    • 不错,这里唯一的问题是您必须为每个对话创建一个新方法。您可以通过向 GetResponse 方法添加 2 个字符串参数来解决此问题,一个是 true 的值,第二个是 false 的值。只是一个建议。
    • @JoJo - 当然可以。如果响应取决于其他因素(性别之外),则可以将其作为参数传递到特定的 GetResponse 方法中。
    • 更好的方法可能是让FemaleMale 成为符合接口的类,并且每个都提供自己的string DesertSalutation() 实现,例如
    • 遗憾的是每次对话都可能不同,我认为此时我有三十个不同的场景,每个场景平均有五个不同的变量选项。
    • @Eric.E 检查我的其他评论(列表中的第一个),有些东西可能有助于使用此解决方案
    【解决方案2】:

    如果您有很多文本,并且有很多可能的变体,我建议您编写一些代码来为您生成字符串。无论如何,将它们混在源代码中似乎不太好(恕我直言)。

    一些xml怎么样?

    <Message Key="message123">
        <Text>It's nice to meet you </Text>
        <Switch Field="Gender">
            <Female>
                Miss, what's a pretty young thing like you
                doing out in the dessert?
            </Female>
            <Male>Sir, what can I do for ya?</Male>
        </Switch>
        <Text> the man asks in a drawl</Text>
    </Message>
    

    &lt;If&gt; 语句和其他内容添加一些代码,您将拥有很大的灵活性。 IE。基于其他变量(例如健康或库存物品)的不同文本。

    不是你的问题的真正答案,但我想我还是会加两分钱。

    【讨论】:

      【解决方案3】:

      编写插入字符串的类StringInterpolated(名称并不重要)(以您的格式)。唯一的缺点是您必须在最后附加参数 - 在您的示例中为 Female

      根据您的需要,您可以使用任何语法来插入您想要的字符串,您还可以添加一个检查是否传递了所有带值的参数,这样就可以覆盖这一面。

      【讨论】:

        【解决方案4】:

        如果这是您的目标,那么 c# 真的不适合您。它根本不提供此功能,虽然它will offer string interpolation in version 6.0,但我怀疑它是否会支持您想要的完整语句。这种特性根本不是该语言的目标,实际上会使主要目标之一(一流的工具支持)变得更加困难。

        一个有趣的替代方法可能是编写在 powershell 中进行插值的代码,该代码是动态的 supports full string interpolation,自 Windows XP 3 以来已安装在每台 Windows 机器上,并且可以与任何 .Net 语言进行本机互操作。

        您甚至可以通过 calling powershell for just that one component 在 c# 中编写其余代码来做到这一点。

        由于 ifs 的 powershell 语法看起来与 c# 非常相似,因此您的代码可能看起来像

        interpolate(@"'It's nice to meet you $(if (Female){ ""Miss, what's a pretty 
        young thing like you doing out in the dessert.""} else { ""Sir, what can I 
        do for ya?""})' the man asks in a drawl.");
        

        话虽如此,这样做并不是很简单,但如果 c# 代码文件中的字符串插值是必须具备的,那么它可能是您的最佳选择。

        其他选择:

        • 同样的事情,但使用任何其他支持插值的 .Net 语言而不是 Powershell
        • 将您的字符串编写为 Razor 模板并使用 RazorEngine 编译它们
        • 使用即将推出的 Roslyn 编译器的功能将字符串编译为 c#。

        这些东西都不是更容易,但都是可行的。

        【讨论】:

        • George,实际上 6.0 的功能看起来正是我想要的。我要去看看它,但非常感谢您的回复。我在工作中经常使用 PowerShell,但没想到在这个个人项目中利用它,但我现在会。
        • 我见过的最糟糕的建议——每种语言本身都包含一些特性,如果你有额外的东西,你可以编写类/函数/库。缺少这样的功能并不是切换整个语言的原因。
        • 我也没有写他应该切换@greenoldman。我没有提到 powershell 与 c# 本地互操作,并链接到一篇关于如何从 powershell 调用 ps 组件的文章。操作员问如何在 c# 中做一些不可能的事情,我指给他如何做下一个最好的事情。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-07-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多