C#中的Spintax...我该如何处理?

4

Spintax允许您旋转各种单词和句子,例如:

{Hello|Hi} {World|People}! {C{#|++|}|Java} is an {awesome|amazing} language.

大括号之间的文本将被随机选择以形成不同的句子。

我可能自己想出解决方案,但问题在于嵌套。有时嵌套可能非常深。如何处理嵌套可能是一个可能的解决方案?

我无法收集所需的逻辑。


这确实短了一点。只有一个要点,快速连续实例化大量随机数并不是一个好主意,因为它们都将具有相同的起始种子。这就是为什么我传递了一个随机数生成器实例,以便它不会这样做的原因。 - paxdiablo
我完全忘记了那件事!谢谢。 - Sian Jakey Ellis
2个回答

9
不要担心嵌套问题,按照以下步骤迭代执行:
1. 查找字符串中第一个没有其他大括号的'{...}'序列。对于您的情况,这是'{Hello | Hi}'。如果没有更多该模式,请转到步骤3。
2. 抓取其中所有可能性并选择一个随机值,将括号部分替换为其值。然后返回步骤1。
3. 修改后的字符串就在那里。
假设您有一个略有缺陷的随机数生成器,它总是返回零。那么您的字符串修改历史记录将如下所示:
a/ {Hello|Hi} {World|People}! {C{#|++|}|Java} 是一种 {awesome|amazing} 语言。 b/ Hello {World|People}! {C{#|++|}|Java} 是一种 {awesome|amazing} 语言。 c/ Hello World! {C{#|++|}|Java} 是一种 {awesome|amazing} 语言。 d/ Hello World! {C#|Java} 是一种 {awesome|amazing} 语言。 e/ Hello World! C# 是一种 {awesome|amazing} 语言。 f/ Hello World! C# 是一种绝妙的语言。
特别注意从(c)到(d)的转变。因为我们正在寻找第一个没有内部大括号的大括号部分,所以在{C {# | ++ |} | Java}之前要进行{# | ++ |}
现在您需要添加的唯一可能性是您的实际文本中可能会有{}|-这些都需要以某种方式进行转义,以使它们免受修改引擎的保护。
以下是一个小型C#程序,展示了这个过程。鉴于我相对于该语言的经验不足,它可能并不那么令人印象深刻,但它说明了这个过程。
using System;
using System.Text.RegularExpressions;

namespace ConsoleApplication1
{
    class Program
    {
        static string spintax(Random rnd, string str) {
            // Loop over string until all patterns exhausted.
            string pattern = "{[^{}]*}";
            Match m = Regex.Match(str, pattern);
            while (m.Success) {
                // Get random choice and replace pattern match.
                string seg = str.Substring(m.Index + 1, m.Length - 2);
                string[] choices = seg.Split('|');
                str = str.Substring(0, m.Index) + choices[rnd.Next(choices.Length)] + str.Substring(m.Index + m.Length);
                m = Regex.Match(str, pattern);
            }

            // Return the modified string.
            return str;
        }

        static void Main(string[] args) {
            Random rnd = new Random();
            string str = "{Hello|Hi} {World|People}! {C{#|++|}|Java} is an {awesome|amazing} language.";
            Console.WriteLine(spintax(rnd, str));
            Console.ReadLine();
        }
    }
}

以下是一个示例运行的输出结果:

你好,世界!C# 是一门很棒的编程语言。

我从未考虑过迭代地完成它。谢谢!至于文本中的{}和|,我认为我会使任何不符合语法规则的内容被忽略。 - Sian Jakey Ellis
我正在看着你的一块C#代码,想知道那个 空隙在那里做什么 :) - BoltClock
@BoltClock:我不太喜欢代码只长一两行时出现滚动条。对于500行的大型代码,滚动条可以避免页面过于拥挤,但如果可能的话,我更愿意一次性看到所有代码。如果这个问题困扰了足够多的人,我会停止这样做——我经常想知道其他使用屏幕较高的笔记本电脑的人是否也有这个问题。事实上,算了,我要从现在开始停止这样做 :-) - paxdiablo
嗯,我并不在意,但你提到的那些滚动条确实很有道理。 - BoltClock
@paxdiablo,请检查一下我的解决方案,简单多了 :p 但是我是基于你的伪代码编写的。只需要添加逻辑检查即可。 - Sian Jakey Ellis
@paxdiablo 我认为你的输出是有问题的。 - DidIReallyWriteThat

2

我倾向于创建一个递归方法来处理解析。编写一个方法,它接受一个字符串,扫描第一层大括号,并从其中选取随机选项。然后该方法将使用所选选项字符串调用自身,然后将其插入到最终结果中。


你的递归想法已经被实现了。我的解决方案在我上面的回答中。谢谢。我现在不知道该投谁的票了,两个答案都帮了很大的忙。 - Sian Jakey Ellis

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