Despite the apparent evidence, I believe that inheritance is useless here. At a minimum, there will be many classes, each of which must not only be defined, but also initialized. Specifically, to define seniority, it is enough to define the seniority attribute and the can_hit?
method can_hit?
. This will be sufficient both for defining precedence and for redefining (that same example, when a deuce can beat an ace).
class Card attr_reader :name, :seniority, :hitable_seniorities def initialize(name, seniority, hitable_seniorities) @name = name @seniority = seniority @hitable_seniorities = hitable_seniorities end def can_hit?(other_card) hitable_seniorities.include?(other_card.seniority) end end
For example, this is how we determine that a deuce can beat an ace:
Card.new("two", 2, [14])
Well, it remains to determine the factory:
def build_deck(cards_params) cards_params.map { |card_params| Card.new(*card_params) } end
Example of use:
build_deck([ ["three", 3, [2]], ["seven", 7, [2, 3, 4, 5, 6]], ["ace", 14, [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]] ])
I deliberately did not take into account the suit in the examples. about them there was nothing in the question. To use the suits (especially with regard to cards such as the joker), you will most likely need to use compositions (see Practical Object-Oriented Design in Ruby , chapter Combining Objects with Composition
). But the general direction of thought, I hope, is understandable.
UPD:
Made a small example. Suits also differ in seniority, but in order to make the example more complete, they are compared by the “traditional” method.
class Suit attr_reader :name, :seniority def intialize(name, seniority) @name = name @seniority = seniority @trump = false end def trump! @trump = true end def trump? @trump end def same?(other_suit) seniority == other_suit.seniority end def highter?(other_suit) return false if same?(other_suit) return true if trump? seniority > other_suit.seniority end end class Card attr_reader :name, :seniority, :hitable_seniorities, :suit def initialize(name, seniority, hitable_seniorities, suit) @name = name @seniority = seniority @hitable_seniorities = hitable_seniorities @suit = suit end def can_hit?(other_card) #hitable_seniorities.include?(other_card.seniority) return true if suit_highter?(other_card) return false unless same_suit?(other_card) seniority_highter?(other_card) end private def suit_highter?(other_card) suit.highter?(other_card.suit) end def same_suit?(other_card) suit.same?(other_card.suit) end def seniority_highter?(other_card) hitable_seniorities.include?(other_card.seniority) end end class Game attr_reader :suits_factory, :deck_factory attr_reader :suits, :deck def initialize(suits_factory, deck_factory) @suits_factory = suits_factory @deck_factory = deck_factory end def new_game! build_deck! choose_tramp! end private def build_deck! @suits = suits_factory.build @deck = deck_factory.build(suits) end def choose_tramp! @suits.example.trump! end end class SuitsFactory attr_reader :suits_data def initialize(suits_data) # возможные масти в игре @suits_data = suits_data end def build suits_data.map do |suit_data| Suit.new(*suit_data) end end end class DesckFactory attr_reader :cards_data def initialize(cards_data) # возможные в игре достоинства карт @cards_data = cards_data end def build(suits) suits.map { |suits| build_for_suit(suit) }.flatten end private def build_for_suit(suit) cards_data.map do |card_data| Suit.new(*card_data, suit) end end end suits_factory = SuitsFactory.new([ ["Clubs", 1], ["Diamonds", 2], ["Hearts", 3], ["Diamonds", 4] ]) desk_factory = DesckFactory.new([ ["three", 3, [2]], ["seven", 7, [2, 3, 4, 5, 6]], ["ace", 14, [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]] ])
Example of use:
game = Game.new(suits_factory, desk_factory) game.new_game!
force
(number) andis_trump
(boolean) fields to the class of each map. And check them out as needed. - eanmos