OOD的垄断游戏?

时间:2011-01-01 23:19:32

标签: oop design-patterns architecture

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

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

  

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

...这可能意味着你可以使用设计模式来模拟游戏规则(见上文)。有没有人这样做过?使用设计模式设计垄断游戏?如果是这样,它是如何运作的?

3 个答案:

答案 0 :(得分:24)

这就是我如何设计垄断。我冒昧地采用动态类型语言,因为这样可以使一切变得更容易。特别是Ruby。

你有一个简单的Game对象,它主要是一个大小为40的Array的包装器,加上一些便利方法。 Game对象还会跟踪可用houseshotels的数量以及两堆Chance和Community Chest卡。提供了一些方便的方法,如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 and 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 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

答案 1 :(得分:5)

我认为你在这里采取了错误的道路。

...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 

这并不意味着你可以使用设计模式来模拟游戏规则,这意味着无论你在解决方案中做什么,它都可能落在一些已知的设计模式上。然后更容易将您的解决方案视为一组互连模式,而不是从头开始描述所有内容。

答案 2 :(得分:3)

我从来没有设计过垄断规则(太容易了,但也很简单),但是我已经为其他知名游戏编写引擎以获得个人乐趣,并且理解所有这些都是学术活动。

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

使用D&amp; D,重点在于非常好的OO设计 - 使类和层次结构变得有意义。

使用M:tG,你基本上意识到直接的OO范式对于这种事情是不完整的。然后,您最终使用代理,事件代理和创建非常复杂的规则集。

除非你是游戏设计师,否则这一切都毫无意义。但是很有趣。