Александър обнови решението на 11.11.2015 07:53 (преди около 9 години)
+WAR_RANK_ORDER = [2, 3, 4, 5, 6, 7, 8, 9, 10, :jack, :queen, :king, :ace]
+BELOTE_RANK_ORDER = [7, 8, 9, :jack, :queen, :king, 10, :ace]
+SIXTY_SIX_RANK_ORDER = [9, :jack, :queen, :king, 10, :ace]
+
+WAR_HAND_SIZE = 26
+BELOTE_HAND_SIZE = 8
+SIXTY_SIX_HAND_SIZE = 6
+
+class Card
+ attr_reader :rank, :suit
+
+ def initialize(rank, suit)
+ @rank, @suit = rank, suit
+ end
+
+ def to_s
+ rank.to_s.capitalize + " of " + suit.to_s.capitalize
+ end
+
+ def ==(other)
+ other.class == self.class && other.state == self.state
+ end
+
+ protected
+
+ def state
+ [@rank, @suit]
+ end
+end
+
+class CardsHeap
+ def initialize(cards)
+ @cards = cards.dup
+ end
+
+ def size
+ @cards.size
+ end
+
+ private
+
+ def ordered_ranks
+ []
+ end
+
+ def ordered_suits
+ [:spades, :hearts, :diamonds, :clubs]
+ end
+
+ def n_consecutive?(n, allowed_ranks: nil, allowed_suits: nil)
+ @cards.combination(n).select do |c|
+ c.all? do |e|
+ correct_ranks = allowed_ranks.nil? || allowed_ranks.include?(e.rank)
+ correct_suits = allowed_suits.nil? || allowed_suits.include?(e.suit)
+ e.suit == c.first.suit and correct_suits and correct_ranks
+ end
+ end.any? do |c|
+ rank_orders = c.map { |e| ordered_ranks.index(e.rank) }
+ (rank_orders.max - rank_orders.min + 1) == n
+ end
+ end
+end
+
+class WarHand < CardsHeap
+ def play_card
+ @cards.pop
+ end
+
+ def allow_face_up?
+ size <= 3
+ end
+end
+
+class BeloteHand < CardsHeap
+ def highest_of_suit(suit)
+ rank_order = BELOTE_RANK_ORDER
+ @cards.select { |c| c.suit == suit }.max do |a, b|
+ rank_order.index(a.rank) <=> rank_order.index(b.rank)
+ end
+ end
+
+ def belote?
+ n_consecutive?(2, allowed_ranks: [:queen, :king])
+ end
+
+ def tierce?
+ n_consecutive?(3)
+ end
+
+ def quarte?
+ n_consecutive?(4)
+ end
+
+ def quint?
+ n_consecutive?(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
+
+ private
+
+ def ordered_ranks
+ BELOTE_RANK_ORDER
+ end
+
+ def carre_of_rank?(rank)
+ @cards.count { |c| c.rank == rank } >= 4
+ end
+end
+
+class SixtySixHand < CardsHeap
+ def twenty?(trump_suit)
+ allowed_ranks = [:queen, :king]
+ allowed_suits = ordered_suits - trump_suit
+ n_consecutive(2, allowed_ranks: allowed_ranks, allowed_suits: allowed_suits)
+ end
+
+ def forty?(trump_suit)
+ n_consecutive(2, allowed_ranks: [:queen, :king], allowed_suits: trump_suit)
+ end
+
+ def ordered_ranks
+ BELOTE_RANK_ORDER
+ end
+end
+
+class Deck < CardsHeap
+ include Enumerable
+
+ def initialize(cards = nil)
+ @cards = cards ? cards.dup : preferred_cards
+ end
+
+ def each
+ @cards.each { |e| yield e }
+ end
+
+ def draw_top_card
+ @cards.shift
+ end
+
+ def draw_bottom_card
+ @cards.pop
+ end
+
+ def top_card
+ @cards.first
+ end
+
+ def bottom_card
+ @cards.last
+ end
+
+ def shuffle
+ @cards.shuffle!
+ end
+
+ def sort
+ @cards.sort! do |a, b|
+ rank_order_a = ordered_ranks.index(a.rank)
+ rank_order_b = ordered_ranks.index(b.rank)
+ suit_order_a = ordered_suits.index(a.suit)
+ suit_order_b = ordered_suits.index(b.suit)
+ [suit_order_a, rank_order_b] <=> [suit_order_b, rank_order_a]
+ end
+ end
+
+ def to_s
+ @cards.join("\n")
+ end
+
+ def deal
+ hand_class.new(@cards.first(hand_size))
+ end
+
+ private
+
+ def preferred_cards
+ ordered_ranks.product(ordered_suits).map { |p| Card.new(p[0], p[1]) }
+ end
+
+ def hand_class
+ CardsHeap
+ end
+
+ def hand_size
+ 0
+ end
+end
+
+class WarDeck < Deck
+ private
+
+ def ordered_ranks
+ WAR_RANK_ORDER
+ end
+
+ def hand_class
+ WarHand
+ end
+
+ def hand_size
+ WAR_HAND_SIZE
+ end
+end
+
+class BeloteDeck < Deck
+ private
+
+ def ordered_ranks
+ BELOTE_RANK_ORDER
+ end
+
+ def hand_class
+ BeloteHand
+ end
+
+ def hand_size
+ BELOTE_HAND_SIZE
+ end
+end
+
+class SixtySixDeck < Deck
+ private
+
+ def ordered_ranks
+ SIXTY_SIX_RANK_ORDER
+ end
+
+ def hand_class
+ SixtySixHand
+ end
+
+ def hand_size
+ SIXTY_SIX_HAND_SIZE
+ end
+end