我通过CodingHorror找到了这篇有趣的博文:My Favorite Interview Question。简而言之,他谈到了设计垄断游戏的面向对象设计挑战,重点是如何模拟游戏规则。例如,“如果玩家拥有波罗的海大道,她可以为其添加房屋吗?”
有趣的是,在帖子底部附近,他写道:
你可以节省很多面试时间。而不是所有这些喧嚣,请求候选人描述他们何时实际使用框架之外的策略,访问者和命令模式。)
...这可能意味着你可以使用设计模式来模拟游戏规则(见上文)。有没有人这样做过?使用设计模式设计垄断游戏?如果是这样,它是如何运作的?
答案 0 :(得分:24)
这就是我如何设计垄断。我冒昧地采用动态类型语言,因为这样可以使一切变得更容易。特别是Ruby。
你有一个简单的Game
对象,它主要是一个大小为40的Array
的包装器,加上一些便利方法。 Game
对象还会跟踪可用houses
和hotels
的数量以及两堆Chance和Community Chest卡。提供了一些方便的方法,如current_turn
和next_turn!
- 都返回Player
个对象; next_turn!
递增转弯指数,必要时换行为0.
玩家可以登陆的所有位置必须从Property
的超类继承。 Property
类定义了一些常见内容,例如rent
,owner
,set
,houses
,purchasable?
和upgradeable?
。 rent
和owner
属性可能为nil
。 set
属性返回包含组内所有属性的Array
。 set
属性的大小可能会在1到4之间变化。houses
属性代表酒店为5'房屋。
Game
对象有Array
个Player
个对象,每个对象的字段类似position
(0到39之间的整数),money
(否)上限 - 银行在技术上永远不会“没钱”),get_out_of_jail_frees
和in_jail?
(因为这个位置不够用)。 Game
对象还有一个索引来跟踪它的转向。
属性特定规则都在其各自的子类中编码。因此,例如,rent
上Railroad
的实施将是:
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)