Теодор обнови решението на 09.11.2015 07:30 (преди около 9 години)
+# => A classic playing card that has a suit and a rank
+class Card
+ SUITS = [:spades, :hearts, :diamonds, :clubs]
+ RANKS = [:ace, :king, :queen, :jack].concat 10.downto(2).to_a
+
+ attr_reader :rank, :suit
+
+ def initialize(rank, suit)
+ @rank = rank
+ @suit = suit
+ end
+
+ def ==(other)
+ @rank == other.rank && @suit == other.suit
+ end
+
+ def to_s
+ "#{@rank.to_s.capitalize} of #{suit.to_s.capitalize}"
+ end
+end
+
+# => A set of rules for sorting a deck of cards
+module GameRules
+ def sort_cards(cards)
+ cards.sort! do |left, right|
+ compared_suits = suit_index(left) <=> suit_index(right)
+ compared_ranks = rank_index(left) <=> rank_index(right)
+ compared_suits == 0 ? compared_ranks : compared_suits
+ end
+ end
+
+ def suit_index(card)
+ suits.index(card.suit)
+ end
+
+ def rank_index(card)
+ ranks.index(card.rank)
+ end
+
+ def suits
+ Card::SUITS
+ end
+
+ def ranks
+ Card::RANKS
+ end
+
+ def total_cards
+ suits.count * ranks.count
+ end
+end
+
+# => A deck of playing cards
+class Deck < Array
+ include GameRules
+
+ def initialize(cards = nil)
+ super(cards || default_cards)
+ end
+
+ def default_cards
+ suits.product(ranks).map { |suit, rank| Card.new(rank, suit) }
+ end
+
+ def to_s
+ @cards.join("\n")
+ end
+
+ alias_method :top_card, :first
+ alias_method :bottom_card, :last
+
+ alias_method :draw_top_card, :shift
+ alias_method :draw_bottom_card, :pop
+
+ alias_method :shuffle, :shuffle!
+
+ def sort
+ sort_cards self
+ end
+end
+
+# => Cards that a player holds in his/hers hand to play with
+class Hand < Array
+ include GameRules
+
+ def initialize(cards)
+ super sort_cards cards
+ end
+end
+
+# THE GAME OF WAR
+
+# => A deck of cards, that follows the rules of "War"
+class WarDeck < Deck
+ include GameRules
+
+ def deal
+ WarHand.new slice! 0...(total_cards / 2)
+ end
+end
+
+# => A hand of cards, that follows the rules of "War"
+class WarHand < Array
+ include GameRules
+
+ alias_method :play_card, :pop
+
+ def allow_face_up?
+ size < 4
+ end
+end
+
+# THE GAME OF BELOTE
+
+# => The rules of a real game of cards, unlike "War"... :)
+module RealCardGameRules
+ include GameRules
+
+ def carre_of_rank?(rank)
+ 4 == count { |card| card.rank == rank }
+ end
+
+ def sequence_of_size?(size)
+ suits.any? do |suit|
+ not get_sequences(suit, size).empty?
+ end
+ end
+
+ def get_sequences(suit, size)
+ each_cons(size).select do |cards|
+ cards.all? { |card| card.suit == suit } &&
+ sequence_of_ranks?(cards)
+ end
+ end
+
+ def sequence_of_ranks?(cards)
+ ranks.each_cons(cards.size).include? cards.map(&:rank)
+ end
+
+ def queen_and_king_of_suit?(suit)
+ get_sequences(suit, 2).any? do |cards|
+ [:king, :queen] == cards.map(&:rank)
+ end
+ end
+end
+
+# => The rules of "Belote"
+module BeloteRules
+ include RealCardGameRules
+
+ BELOTE_RANKS = [0, 4, 1, 2, 3, 5, 6, 7].map { |x| Card::RANKS[x] }
+
+ def ranks
+ BELOTE_RANKS
+ end
+end
+
+# => A deck of cards, that follows the rules of "Belote"
+class BeloteDeck < Deck
+ include BeloteRules
+
+ def deal
+ BeloteHand.new slice! 0...(total_cards / 4)
+ end
+end
+
+# => A hand of cards, that follows the rules of "Belote"
+class BeloteHand < Hand
+ include BeloteRules
+
+ def highest_of_suit(suit)
+ sort_cards(select { |card| card.suit == suit }).last
+ end
+
+ def belote?
+ suits.any? { |suit| queen_and_king_of_suit? suit }
+ end
+
+ def tierce?
+ sequence_of_size? 3
+ end
+
+ def quarte?
+ sequence_of_size? 4
+ end
+
+ def quint?
+ sequence_of_size? 5
+ end
+
+ def carre_of_jacks?
+ carre_of_rank? :jack
+ end
+
+ def carre_of_nines?
+ carre_of_rank? 9
+ end
+
+ def carre_of_aces?
+ carre_of_rank? :ace
+ end
+end
+
+# THE GAME OF SIXTY SIX
+
+# => The rules of "Sixty-Six"
+module SixtySixRules
+ include RealCardGameRules
+
+ SIXTY_SIX_RANKS = [0, 4, 1, 2, 3, 5].map { |x| Card::RANKS[x] }
+
+ def ranks
+ SIXTY_SIX_RANKS
+ end
+end
+
+# => A deck of cards, that follows the rules of "Sixty-Six"
+class SixtySixDeck < Deck
+ include SixtySixRules
+
+ def deal
+ SixtySixHand.new slice! 0...(total_cards / 4)
+ end
+end
+
+# => A hand of cards, that follows the rules of "Sixty-Six"
+class SixtySixHand < Hand
+ include SixtySixRules
+
+ def twenty?(trump_suit)
+ non_trump_suits = suits - [trump_suit]
+ non_trump_suits.any? { |suit| queen_and_king_of_suit? suit }
+ end
+
+ def forty?(trump_suit)
+ queen_and_king_of_suit? trump_suit
+ end
+end