София обнови решението на 11.11.2015 15:37 (преди около 9 години)
+class Card
+ attr_reader :rank, :suit
+
+ def initialize(rank, suit)
+ @rank = rank
+ @suit = suit
+ end
+
+ def to_s
+ "#{@rank.to_s.capitalize} of #{@suit.capitalize}"
+ end
+
+ def ==(another_card)
+ self.class == another_card.class && state == another_card.state
+ end
+
+ protected
+ def state
+ [@rank, @suit]
+ end
+end
+
+class Deck
+SUITS = [:clubs, :diamonds, :hearts, :spades]
+RANKS = [2, 3, 4, 5, 6, 7, 8, 9, 10, :jack, :queen, :king, :ace]
+
+ include Enumerable
+
+ attr_accessor :deck
+
+ def initialize(deck = nil)
+ @deck = if deck
+ deck
+ else
+ RANKS.product(SUITS).collect {|rank, suit| Card.new(rank, suit)}
+ end
+ end
+
+ def each(&block)
+ @deck.each(&block)
+ end
+
+ def size
+ @deck.size
+ end
+
+ def draw_top_card
+ @deck.shift
+ end
+
+ def draw_bottom_card
+ @deck.pop
+ end
+
+ def top_card
+ @deck[0]
+ end
+
+ def bottom_card
+ @deck[-1]
+ end
+
+ def shuffle
+ @deck = deck.shuffle
+ end
+
+ def sort
+ @deck = @deck.sort do |first_card, second_card|
+ if first_card.suit == second_card.suit
+ rank_index(first_card.rank) <=> rank_index(second_card.rank)
+ else
+ suit_index(first_card.suit) <=> suit_index(second_card.suit)
+ end
+ end
+ end
+
+ def to_s
+ printed_deck = @deck.each {|card| puts card}
+ end
+
+ private
+
+ def suit_index(suit)
+ Deck::SUITS.reverse.index(suit)
+ end
+
+ def rank_index(rank)
+ Deck::RANKS.reverse.index(rank)
+ end
+end
+
+class WarDeck < Deck
+
+ def deal
+ draw = Hand.new
+ 26.times { draw.hand << @deck.pop }
+ draw
+ end
+
+ class Hand
+ attr_accessor :hand
+
+ def initialize(hand = [])
+ @hand = hand
+ end
+
+ def size
+ @hand.size
+ end
+
+ def allow_face_up?
+ @hand.size <= 3
+ end
+
+ def play_card
+ @hand.shift
+ end
+ end
+
+end
+
+class BeloteDeck < Deck
+ RANKS = [7, 8, 9, :jack, :queen, :king, 10, :ace]
+ SUITS = [:clubs, :diamonds, :hearts, :spades]
+
+ def initialize(deck = nil)
+ @deck = if deck
+ deck
+ else
+ RANKS.product(SUITS).collect {|rank, suit| Card.new(rank, suit)}
+ end
+ end
+
+ def deal
+ draw = Hand.new
+ 8.times { draw.hand << @deck.pop }
+ draw
+ end
+
+ def size
+ @hand.size
+ end
+
+ def sort
+ @deck = @deck.sort do |first_card, second_card|
+ if first_card.suit == second_card.suit
+ rank_index(first_card.rank) <=> rank_index(second_card.rank)
+ else
+ suit_index(first_card.suit) <=> suit_index(second_card.suit)
+ end
+ end
+ end
+
+ class Hand
+ attr_accessor :hand
+ def initialize(hand = [])
+ @hand = hand
+ end
+
+ def size
+ @hand.size
+ end
+
+ def highest_of_suit(suit)
+ suits_allowed = @hand.find_all {|card| card.suit == suit}
+ suits_allowed = suits_allowed.sort do |first_card, second_card|
+ rank_index(first_card.rank) <=> rank_index(second_card.rank)
+ end
+ suits_allowed.first
+ end
+
+ def belote?
+ kings = @hand.find_all {|card| card.rank == :king }
+ kings_suits = kings.map { |card| card.suit }
+
+ queens = @hand.find_all { |card| card.rank == :queen }
+ queens_suits = queens.map { |card| card.suit }
+
+ kings_suits - queens_suits != kings_suits
+ end
+
+ def tierce?
+ sorted_hand = @hand.sort do |first_card, second_card|
+ rank_index(first_card.rank) <=> rank_index(second_card.rank)
+ end
+ sorted_hand.each_cons(3).any? do |first_card, second_card|
+ ((rank_index(second_card.rank) == rank_index(first_card.rank) + 1) &&
+ first_card.suit == second_card.suit)
+ end
+ end
+
+ def quarte?
+ sorted_hand = @hand.sort do |first_card, second_card|
+ rank_index(first_card.rank) <=> rank_index(second_card.rank)
+ end
+ sorted_hand.each_cons(4).any? do |first_card, second_card|
+ ((rank_index(second_card.rank) == rank_index(first_card.rank) + 1) &&
+ first_card.suit == second_card.suit) end
+ end
+
+ def quint?
+ sorted_hand = @hand.sort do |first_card, second_card|
+ rank_index(first_card.rank) <=> rank_index(second_card.rank)
+ end
+ sorted_hand.each_cons(5).any? do |first_card, second_card|
+ ((rank_index(second_card.rank) == rank_index(first_card.rank) + 1) &&
+ first_card.suit == second_card.suit)
+ end
+ end
+
+ def carre_of_jacks?
+ jacks = @hand.find_all {|card| card.rank == :jack}
+ jacks.length == 4
+ end
+
+ def carre_of_nines?
+ nines = @hand.find_all {|card| card.rank == 9}
+ nines.length == 4
+ end
+
+ def carre_of_aces?
+ aces = @hand.find_all {|card| card.rank == :ace}
+ aces.length == 4
+ end
+
+ private
+
+ def rank_index(rank)
+ BeloteDeck::RANKS.reverse.index(rank)
+ end
+ end
+
+ private
+
+ def suit_index(suit)
+ BeloteDeck::SUITS.reverse.index(suit)
+ end
+
+ def rank_index(rank)
+ BeloteDeck::RANKS.reverse.index(rank)
+ end
+end
+
+
+class SixtySixDeck < Deck
+RANKS = [9, :jack, :queen, :king, 10, :ace]
+SUITS = [:clubs, :diamonds, :hearts, :spades]
+
+ def initialize(deck = nil)
+ @deck = if deck
+ deck
+ else
+ RANKS.product(SUITS).collect {|rank, suit| Card.new(rank, suit)}
+ end
+ end
+
+ def deal
+ draw = Hand.new
+ 6.times do draw.hand << @deck.pop end
+ draw
+ end
+
+ def size
+ @hand.size
+ end
+
+ def sort
+ @deck = @deck.sort do |first_card, second_card|
+ if first_card.suit == second_card.suit
+ rank_index(first_card.rank) <=> rank_index(second_card.rank)
+ else
+ suit_index(first_card.suit) <=> suit_index(second_card.suit)
+ end
+ end
+ end
+
+ class Hand
+ attr_accessor :hand
+ def initialize(hand = [])
+ @hand = hand
+ end
+
+ def size
+ @hand.size
+ end
+
+ def twenty?(trump_suit)
+ @hand.any? {|card| card.rank == :king && card.suit != trump_suit } &&
+ @hand.any? {|card| card.rank == :queen && card.suit != trump_suit }
+ end
+
+ def forty?(trump_suit)
+ @hand.any? {|card| card.rank == :king && card.suit == trump_suit } &&
+ @hand.any? {|card| card.rank == :queen && card.suit == trump_suit }
+ end
+ end
+
+ private
+
+ def suit_index(suit)
+ SixtySixDeck::SUITS.reverse.index(suit)
+ end
+
+ def rank_index(rank)
+ SixtySixDeck::RANKS.reverse.index(rank)
+ end
+end