Ruby 基于OOP的文本游戏中优雅的命令解析

Ruby 基于OOP的文本游戏中优雅的命令解析,ruby,language-agnostic,oop,nlp,Ruby,Language Agnostic,Oop,Nlp,我正在玩用Ruby写一篇泥浆/文本冒险(请不要笑)。有谁能给我一个优雅的、基于oop的输入文本解析解决方案的建议吗 在这里,我们谈论的并没有什么比“把魔杖放在桌子上”更复杂的了。但一切都需要柔软;稍后,我想毫无痛苦地扩展命令集 我现在的想法稍微简化了: 每个物品类别(盒子、桌子、房间、玩家)都知道如何识别“属于”它的命令 游戏类理解一种特定于领域的语言,涉及诸如“在对象Y中移动对象X”、“显示对象X的描述”等动作 游戏类询问房间中的每个项目是否识别输入命令。首先说“是”的人获胜 然后,它将控制权

我正在玩用Ruby写一篇泥浆/文本冒险(请不要笑)。有谁能给我一个优雅的、基于oop的输入文本解析解决方案的建议吗

在这里,我们谈论的并没有什么比“把魔杖放在桌子上”更复杂的了。但一切都需要柔软;稍后,我想毫无痛苦地扩展命令集

我现在的想法稍微简化了:

  • 每个物品类别(盒子、桌子、房间、玩家)都知道如何识别“属于”它的命令

  • 游戏类理解一种特定于领域的语言,涉及诸如“在对象Y中移动对象X”、“显示对象X的描述”等动作

  • 游戏类询问房间中的每个项目是否识别输入命令。首先说“是”的人获胜

  • 然后,它将控制权传递给item类中处理该命令的方法。此方法在DSL中重新表述命令,将其传递回游戏对象以使其发生


  • 做这件事一定有老套、优雅的方法。不过,谷歌似乎什么都找不到。

    这是我所知道的最面向对象的解析方法,但我相信编译器专家会指出更强大的算法。

    将其拆分为标记,因为格式始终是:
    [命令][对象1]([引用][对象2])


    您可以在您房间的[object1]上调用方法[command],并将其传递给[object2],如果适用。

    对于命令解释器,我非常喜欢这种简单而不那么优雅的模式。动态语言中的模式比GOF模式涉及的框和行更少

    class Thing
    
      # Handle a command by calling the method "cmd_" + command.
      # Raise BadCommand exception if there is no method for that command.
    
      def handle_command(command, args)
        method_name = "cmd_#{command}"
        raise BadCommand, command unless respond_to?(method_name)
        send(method_name, args)
      end
    
      def cmd_quit(args)
        # the code for command "quit"
      end
    
      def cmd_list(args)
        # the code for command "list"
      end
    
      ...
    
    end
    

    这样,添加新命令就是添加新方法。无需调整任何表格或案例陈述。

    确定。所以你需要一个语义?(转身是一个动作,点燃一个物体,在一个论点上…(我涉及到你对dbemerlin的评论)

    为什么不定义语法呢?哼。。。我想lex和yacc不是一个选择?(因为这根本不是OOP,但您要做的是“编译”用户输入以生成某些内容-执行一些更改房间数据的代码,并输出结果)

    您可以为您的对象及其操作进行OOP设计(例如,所有对象都有一个.describeMe()方法..),除此之外,还有一个输入解析器+编译器

    我完全偏离主题了吗


    编辑:在查看Marc Seeman指出的解释器模式之后,这似乎是在OOP中使用它的方法。(但您将在某种程度上重新发明轮子)

    听起来您需要一个解析器


    将输入字符串拆分为标记(单词)。然后将令牌一次一个地馈送到状态机。我发现下推自动机是编写这样一个stm的非常直观和强大的方法。

    作为一个脚注,我当前计划的难点在于实现涉及两个对象的操作。你可以从开始,看看这会导致什么。Ta!我刚刚在问题中添加了这个标签。我的第一个勾号是:)我将研究有限状态机和解释器模式。在我看来,后者很符合我目前的想法。但问题在于细节,也就是语法分析。我有很多想法。谢谢大家。我对设计模式一窍不通,我的谷歌搜索也没能看到这个。ta,我一定会看一看。实际上,解释器模式看起来就像编译过程中的表达式树!美好的对于编译器来说,这似乎是一个严格的前瞻性实现。(解析字符串标记后)我仍在努力将此模式应用到我的项目中,但它看起来确实像是我正在摸索的想法。然而,它没有说的是命令字符串的解析方式,这非常诱人。但是,“打开灯”。或者,在这个问题上,能够接受“打开灯”真的很好。你可以通过简单地从字符串中删除通常称为“停止词”的内容来做到这一点。像“the”、“an”、“on”这样的词。在这种情况下,“现在打开那里的灯”这句话只剩下“打开灯”。当然,这可能太多了,但在这种情况下,没有“off”这个词会告诉你你需要知道的一切。@Jorg:事实上,我目前的方法就是这么做的,只是它会检测“start words”。因此(稍微简化一下)light类查找/light.*(开|关)/。也许你有正确的方法,但我没有。停止词的概念来自搜索引擎,这些词根本没有任何用处。因此,它们通常会从索引和搜索查询中过滤掉。这里肯定要调整一下。您可以看看Git版本控制系统中的自然语言日期解析器。它看起来可以解析非常复杂的表达式,比如“大约一个小时前”,但它真正做的是扔掉任何它不理解的东西,所以它只会以“小时”结束,它被简单地定义为
    3600
    ,就是这样。很好,我看过莱克斯和亚克。但是他们让我头疼,这应该是一个有趣的项目。另外,如果我理解正确的话,他们会把我和一个比英语更严格的语法联系在一起。我想我的黄金目标是让用户能够键入“放在桌上的魔杖”并被理解。。。或者至少让游戏试着把桌子放在魔杖上;)关于如何开始研究状态机的概念,有什么建议吗?当然,维基百科条目是给定的。我收回维基百科的评论。关于下推自动机的页面看起来很吸引人,但它是用高等数学编写的。@Shadow:是编译器资源的规范页面。但你需要的是专门的,可能没有得到很好的治疗。这个答案在技术上是正确的,但不是很有帮助,因为自然语言程序