Jeu Monopoly dans OOD?
J'ai trouvé cet article de blog intéressant via CodingHorror: Ma Question D'entrevue préférée . En un mot, il parle des défis de conception orientée objet de la conception du jeu de Monopoly, en mettant l'accent sur la façon de modéliser les règles du jeu. Par exemple, " si un joueur possède Baltic Avenue, peut-elle y ajouter une maison?"
Fait intéressant, près du bas du message, il écrit alors:
, Vous pouvez probablement vous épargner beaucoup de temps d'entrevue. Au lieu de tous les ce cerceau, demander au candidat de décrire quand ils ont effectivement utilisé la stratégie, visiteur, et les modèles de commande en dehors d'un cadre.)
...ce qui signifie probablement que vous pouvez utiliser des modèles de conception pour modéliser les règles du jeu (voir ci-dessus). Personne n'a jamais fait cela? Conçu le jeu de Monopoly en utilisant des modèles de conception? Si oui, comment se fait-il fonctionner?
3 réponses
Voici comment je concevrais Monopoly. J'ai pris la liberté d'assumer un langage typé dynamiquement car cela rend tout plus facile. Ruby spécifiquement.
Vous avez un objet Game
simple qui est principalement un wrapper autour d'un Array
de taille 40, plus quelques méthodes de commodité. L'objet Game
suit également le nombre de houses
et hotels
disponibles ainsi que les deux piles de cartes Chance et Community Chest. Quelques méthodes de commodité comme current_turn
et next_turn!
sont fournies - les deux renvoient un Player
objet; next_turn!
incrémente l'index de tour, en l'enveloppant à 0 si nécessaire.
Tous les emplacements sur lesquels le Joueur peut atterrir doivent hériter d'une superclasse de Property
. Le Property
classe définit un peu de choses en commun comme rent
, owner
, set
, houses
, purchasable?
, et upgradeable?
. Les propriétés rent
et owner
peuvent être nil
. La propriété set
renvoie un Array
contenant toutes les propriétés du groupe. La taille de la propriété set
peut varier de 1 à 4. La propriété houses
représente un hôtel comme 5 "maisons".
Le Game
objet a un Array
de Player
objets, chacun avec des champs comme position
(un entier de 0 à 39), money
(pas de limite supérieure - la banque techniquement jamais "à court d'argent'), get_out_of_jail_frees
, et in_jail?
(depuis la position est insuffisante pour cette). L'objet Game
a également un index pour suivre son tour.
Les règles spécifiques aux propriétés sont toutes codées dans leurs sous-classes respectives. Ainsi, par exemple, l'implémentation de rent
sur un Railroad
serait être:
def rent
owned_count = self.set.select { |rr| rr.owner == self.owner }.size
return 25 * 2 ** (owned_count - 1)
end
Les cartes Chance et Community Chest peuvent être simplement implémentées avec un tas de fermetures qui prennent un jeu et un objet joueur comme paramètres. Par exemple:
# 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
Et ainsi de suite. La méthode advance_token!
gère évidemment des choses comme passer go.
Évidemment, il y a plus de détails-c'est un jeu assez compliqué, mais j'espère que cela vous donne la bonne idée. Il serais certainement plus que suffisant pour une entrevue.
Mettre à jour
Règles de la maison pourrait être allumé ou éteint en ajoutant un house_rules
Array
à l'objet Game
. Cela permettrait à la propriété FreeParking
d'être implémentée comme ceci:
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
Je pense que vous prenez le mauvais chemin ici.
...which probably means that you can use design patterns to model the rules of the game (see above).
Je pense que cela montre juste que vous ne comprenez pas vraiment ce que sont les modèles de conception. Les Modèles de conception connus ne sont que des noms que nous donnons à des situations récurrentes lors du codage. Dans votre vie de tous les jours, vous ne dites jamais "je me suis réveillé à 8h pour aller à 9h pour placer X, programmant toute la journée jusqu'à 17h, donc ils me paient d'ici la fin du mois". Vous dites: "Aujourd'hui, je suis parti travailler". Vous avez le problème de vouloir gagner de l'argent, et un récurrent les solutions à ce problème vont fonctionner. Si... nous avons un modèle ici! Appelons ça "travailler"!
Les modèles de conception ne sont qu'un tas de solutions étudiées à des problèmes communs. Chacune de ces solutions a un nom associé (stratégie, visiteur, etc.).
Revenir à
...which probably means that you can use design patterns to model the rules of the game
Cela ne signifie pas que vous pouvez utiliser des modèles de conception pour modéliser les règles du jeu, cela signifie que quoi que vous fassiez dans votre solution, il tombera probablement sur certains des modèles de conception connus. Il est plus facile de penser alors à votre solution comme un ensemble de modèles interconnectés que d'avoir à tout décrire à partir du sol.
Je n'ai jamais conçu de règles Monopoly (trop facile, me semble-t-il), mais j'ai tâté d'écrire des moteurs pour d'autres jeux bien connus pour le plaisir personnel et avec la compréhension que tout cela est un exercice académique.
Les deux jeux que j'ai essayé de modèle (et de continuer à essayer) sont , D&D et M:tG.
Avec D & D, l'accent est mis sur de très bonnes classes de conception OO et des hiérarchies de classes qui ont du sens.
Avec M: tG, vous réalisez essentiellement que le le paradigme oo droit est incomplet pour ce genre de chose. Vous finissez par travailler avec des agents, des courtiers d'événements et créer des ensembles de règles vraiment compliqués.
Tout cela n'a pas de sens sauf si vous êtes un concepteur de jeu. Bon amusement, bien que.