【问题标题】:Monopoly game in OOD?OOD中的垄断游戏?
【发布时间】:2011-06-02 08:29:50
【问题描述】:

我通过 CodingHorror 发现了这篇有趣的博文:My Favorite Interview Question。简而言之,他谈到了设计大富翁游戏的面向对象设计挑战,重点是如何对游戏规则进行建模。例如,“如果玩家拥有波罗的海大道,她可以在其中添加房子吗?”

有趣的是,在帖子底部附近,他写道:

您或许可以为自己节省很多面试时间。而不是所有这些喧嚣,请候选人描述他们何时实际使用了框架之外的策略、访问者和命令模式。)

...这可能意味着您可以使用设计模式来模拟游戏规则(见上文)。有没有人这样做过?使用设计模式设计大富翁游戏?如果有,效果如何?

【问题讨论】:

    标签: oop design-patterns architecture


    【解决方案1】:

    这就是我设计 Monopoly 的方式。我冒昧地假设了一种动态类型的语言,因为这使一切变得更容易。特别是 Ruby。

    你有一个简单的 Game 对象,它主要是一个大小为 40 的 Array 的包装器,以及一些方便的方法。 Game 对象还跟踪可用的houseshotels 的数量以及两叠机会卡和公益金卡。提供了一些方便的方法,如current_turnnext_turn! — 都返回一个Player 对象; next_turn! 增加转弯索引,必要时回绕到 0。

    玩家可以登陆的所有位置都必须继承自 Property 的超类。 Property 类定义了一些常见的东西,例如 rentownersethousespurchasable?upgradeable?rentowner 属性可能是 nilset 属性返回包含组内所有属性的Arrayset 属性的大小可能从 1 到 4 不等。houses 属性将酒店表示为 5 个“房屋”。

    Game 对象有一个 ArrayPlayer 对象,每个对象都有 position(从 0 到 39 的整数)、money(没有上限——银行从技术上讲永远不会“耗尽”)钱'),get_out_of_jail_freesin_jail?(因为位置不足以完成此操作)。 Game 对象也有一个索引来跟踪轮到谁了。

    属性特定的规则都被编码在它们各自的子类中。因此,例如,rentRailroad 上的实现将是:

    def rent
      owned_count = self.set.select { |rr| rr.owner == self.owner }.size
      return 25 * 2 ** (owned_count - 1)
    end
    

    Chance 和 Community Chest 卡可以简单地使用一堆闭包来实现,这些闭包将游戏和玩家对象作为参数。例如:

    # Second place in a beauty contest
    COMMUNITY_CHEST_CARDS << lambda do |game, player|
      player.money += 10
    end
    
    # Advance token to Boardwalk
    CHANCE_CARDS << lambda do |game, player|
      game.advance_token!(player, 39)
    end
    
    # Advance token to nearest railroad, pay double
    CHANCE_CARDS << lambda do |game, player|
      new_position = [5, 15, 25, 35].detect do |p|
        p > player.position
      end || 5
      game.advance_token!(player, new_position)
      # Pay rent again, no-op if unowned
      game.properties[new_position].pay_rent!(player)
    end
    

    等等。 advance_token! 方法显然可以处理诸如传递 go 之类的事情。

    显然,还有更多细节——这是一个相当复杂的游戏,但希望这能给你正确的想法。面试肯定绰绰有余。

    更新

    可以通过将house_rules Array 添加到Game 对象来打开或关闭房屋规则。这将允许像这样实现 FreeParking 属性:

    class Game
      def house_rules
        @house_rules ||= []
      end
    
      def kitty
        # Initialize the kitty to $500.
        @kitty ||= 500
      end
    
      def kitty=(new_kitty)
        @kitty = new_kitty
      end
    end
    
    class FreeParking < Property
      def rent
        if self.game.house_rules.include?(:free_parking_kitty)
          # Give the player the contents of the kitty, and then reset it to zero.
          return -(_, self.game.kitty = self.game.kitty, 0)[0]
        else
          return 0
        end
      end
    end
    

    【讨论】:

    • 哇!经过深思熟虑和构建。
    • 如果我没看错的话,作者的主要关注点是几乎没有两个人按照相同的规则玩垄断,因为每个人都有不同的家规,他们习惯了。在您的架构中,更改规则集不会需要在许多不同的地方进行大量的小改动吗?
    • 最常见的房屋规则——通过免费停车赚钱——可以通过为FreeParking 属性添加rent 方法的实现并返回一个负数来轻松实现。这是一个地方的一个小变化。您可以轻松添加分支逻辑来打开和关闭房屋规则。
    • 更新了我的答案,提供了有关如何执行此操作的更多信息。
    • 我认为使用 OP 链接中建议的一些模式的目的是避免做你所做的事情,即通过添加另一个属性来修改 Game 对象并显式修改 FreeParking 的rent 方法。基本上,您希望能够在不修改任何这些对象的情况下添加规则(开闭原则)。
    【解决方案2】:

    我认为你在这里走错路了。

    ...which probably means that you can use design patterns to model the rules of the game (see above). 
    

    我认为这只是表明您并不真正了解设计模式是什么。已知的设计模式只是我们在编码时给经常出现的情况命名。在你的日常生活中,你永远不会说“我早上 8 点起床去早上 9 点放置 X,整天编程直到下午 5 点,所以他们在月底之前付钱给我”。你说,“今天我去上班了”。您有想赚钱的问题,并且该问题的反复解决方案将起作用。所以......我们在这里有一个模式!让我们称之为“工作”!

    设计模式只是针对常见问题的一组经过研究的解决方案。这些解决方案中的每一个都有一个关联的名称(策略、访问者等)。

    回来

    ...which probably means that you can use design patterns to model the rules of the game 
    

    这并不意味着您可以使用设计模式来模拟游戏规则,这意味着无论您在解决方案中做什么,它都可能会落入一些已知的设计模式。与必须从头开始描述所有内容相比,将您的解决方案视为一组相互关联的模式更容易。

    【讨论】:

    • 在哲学上是正确的,但实际上并不是那么简单。 DP 的主要挑战是在问题中识别它们并在解决方案中正确应用它们(在现实生活中相同,顺便说一句,当问题稍微不常见时“去工作”)。这个问题可能应该改写为“可以应用哪些已知的设计模式来简化这个问题的解决方案?”
    • 这个问题可能应该改写为“可以应用哪些已知的设计模式来简化这个问题的解决方案?”我同意。只是在 SO 上看到人们对设计模式完全感到困惑是很常见的,就好像它们是目标(而不是达到目的的手段)..
    【解决方案3】:

    我从来没有设计过大富翁规则(太简单了,我想),但我曾涉足为其他知名游戏编写引擎以供个人娱乐,并理解所有这一切都是一项学术活动。

    我尝试建模(并继续尝试)的两个游戏是D&DM:tG

    对于 D&D,重点是非常好的 OO 设计 - 使类和类层次结构有意义。

    使用 M:tG,您基本上意识到直接的 OO 范式对于这类事情是不完整的。您最终会与代理、事件代理合作,并创建非常复杂的规则集。

    除非您是游戏设计师,否则这一切都毫无意义。不过很好玩。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-03-07
      • 2012-03-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多