Решение на Четвърта задача от Алекс Николов

Обратно към всички решения

Към профила на Алекс Николов

Резултати

  • 4 точки от тестове
  • 0 бонус точки
  • 4 точки общо
  • 42 успешни тест(а)
  • 15 неуспешни тест(а)

Код

module RanksAndSuits
def standard_ranks
{
ace: 1, king: 2, queen: 3, jack: 4,
10 => 5, 9 => 6, 8 => 7, 7 => 8, 6 => 9,
5 => 10, 4 => 11, 3 => 12, 2 => 13,
}
end
def belote_ranks
{ace: 1, 10 => 2, king: 3, queen: 4, jack: 5, 9 => 6, 8 => 7, 7 => 8}
end
def sixty_six_ranks
{ace: 1, 10 => 2, king: 3, queen: 4, jack: 5, 9 => 6}
end
def card_suits
[:spades, :hearts, :diamonds, :clubs]
end
end
module KingsAndQueensMethods
def belote?(cards)
kings_queens = cards.find_all { |x| x.rank == :king or x.rank == :queen }
kings_queens.sort_by! { |x| [x.suit, belote_ranks[x.rank]] }
same_suit = -> (card_group) { card_group[0].suit == card_group[1].suit }
kings_queens.each_cons(2).any?(&same_suit)
end
end
class Card
def initialize(rank, suit)
@rank, @suit = rank, suit
end
attr_reader :rank
attr_reader :suit
def to_s
rank_to_s, suit_to_s = @rank.to_s, @suit.to_s
rank_to_s.capitalize + " of " + suit_to_s.capitalize
end
def ==(rs)
@rank == rs.rank and @suit == rs.suit
end
end
class Deck
include Enumerable, RanksAndSuits
def initialize(cards = nil)
@deal_cards_number = 26
@card_ranks = standard_ranks
initialize_cards(cards)
end
def each
@cards.each { |card| yield card }
end
def size
@cards.size
end
def draw_top_card
@cards.delete_at(0)
end
def draw_bottom_card
@cards.delete_at(-1)
end
def top_card
@cards.first
end
def bottom_card
@cards.last
end
def shuffle
@cards.shuffle!
end
def sort
@cards.sort_by! { |x| [x.suit.to_s, - @card_ranks[x.rank]] }.reverse!
end
def to_s
@cards.each { |card| card.to_s }
end
def deal
Hand.new(cards_to_be_dealt)
end
private
def initialize_cards(cards)
if cards.nil?
@cards = Array.new
rank_and_suit_combinations = @card_ranks.keys.product(card_suits)
rank_and_suit_combinations.each { |x| @cards << Card.new(x[0], x[1]) }
else
@cards = cards
end
end
def cards_to_be_dealt
@cards.shift(@deal_cards_number)
end
end
class Hand
def initialize(card_array)
@cards = card_array
end
attr_reader :cards
def size
@cards.size
end
end
class WarDeck < Deck
def deal
WarHand.new(cards_to_be_dealt)
end
end
class WarHand < Hand
def play_card
@cards.delete_at(0)
end
def allow_face_up?
size <= 3
end
end
class BeloteDeck < Deck
def initialize(cards = nil)
@deal_cards_number = 8
@card_ranks = belote_ranks
initialize_cards(cards)
end
def deal
BeloteHand.new(cards_to_be_dealt)
end
end
class BeloteHand < Hand
include RanksAndSuits
def highest_of_suit(suit)
same_suit_cards = cards.find_all { |x| x.suit == suit }
same_suit_card.min_by { |x| belote_ranks[x.rank] }
end
def belote?
KingsAndQueensMethods.belote?(cards)
end
def tierce?
consecutive_from_same_suit?(3)
end
def quarte?
consecutive_from_same_suit?(4)
end
def quint?
consecutive_from_same_suit?(5)
end
def carre_of_jacks?
four_of_a_kind?(:jack)
end
def carre_of_nines?
four_of_a_kind?(9)
end
def carre_of_aces?
four_of_a_kind?(:ace)
end
private
def consecutive_from_same_suit?(number_of_cards)
sorted_cards = cards.sort_by { |x| [x.suit, - belote_ranks[x.rank]] }
sorted_cards.each_cons(number_of_cards).any? do |card_group|
same_suit = card_group.all? { |card| card.suit == card_group[0].suit }
same_suit and consecutive_cards?(card_group)
end
end
def consecutive_cards?(sorted_card_group)
rank_plus_index = Array.new
sorted_card_group.each_with_index do |card, i|
rank_plus_index[i] = belote_ranks[card.rank] + i
end
rank_plus_index.uniq.length == 1
end
def four_of_a_kind?(rank)
cards.count { |card| card.rank == rank }
end
end
class SixtySixDeck < Deck
def initialize(cards = nil)
@card_ranks = sixty_six_ranks
@deal_cards_number = 6
initialize_cards(cards)
end
def deal
SixtySixHand.new(cards_to_be_dealt)
end
end
class SixtySixHand < Hand
def forty?(trump_suit)
trump_kings_and_queens = cards.find_all do |card|
card.suit == trump_suit and
(card.rank == :queen or card.rank == :king)
end
trump_kings_and_queens.size == 2
end
def twenty?(trump_suit)
KingsAndQueensMethods.belote?(cards) and (not forty?(trump_suit))
end
end

Лог от изпълнението

...........F............F..FFF.......FFFFFF........F..FFF

Failures:

  1) WarDeck behaves like a deck #to_s returns the names of the cards, each on its own line
     Failure/Error: expect(small_deck.to_s.strip).to eq "Ace of Spades\n9 of Clubs"
     NoMethodError:
       undefined method `strip' for #<Array:0x007f0633c8e7f0>
     Shared Example Group: "a deck" called from /tmp/d20151112-27349-1nbyzx3/spec.rb:140
     # /tmp/d20151112-27349-1nbyzx3/spec.rb:68:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  2) BeloteDeck behaves like a deck #to_s returns the names of the cards, each on its own line
     Failure/Error: expect(small_deck.to_s.strip).to eq "Ace of Spades\n9 of Clubs"
     NoMethodError:
       undefined method `strip' for #<Array:0x007f0633b943b8>
     Shared Example Group: "a deck" called from /tmp/d20151112-27349-1nbyzx3/spec.rb:191
     # /tmp/d20151112-27349-1nbyzx3/spec.rb:68:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  3) BeloteDeck hand #highest_of_suit returns the strongest card of the specified suit
     Failure/Error: expect(hand.highest_of_suit(:clubs)).to eq Card.new(:ace, :clubs)
     NameError:
       undefined local variable or method `same_suit_card' for #<BeloteHand:0x007f0633b41d70>
     # /tmp/d20151112-27349-1nbyzx3/solution.rb:161:in `highest_of_suit'
     # /tmp/d20151112-27349-1nbyzx3/spec.rb:232:in `block (4 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  4) BeloteDeck hand #belote? returns true if there is a king and a queen of the same suit
     Failure/Error: expect(hand.belote?).to be true
     NoMethodError:
       undefined method `belote?' for KingsAndQueensMethods:Module
     # /tmp/d20151112-27349-1nbyzx3/solution.rb:165:in `belote?'
     # /tmp/d20151112-27349-1nbyzx3/spec.rb:251:in `block (4 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  5) BeloteDeck hand #belote? returns false when there is no king and queen of the same suit
     Failure/Error: expect(hand.belote?).to be false
     NoMethodError:
       undefined method `belote?' for KingsAndQueensMethods:Module
     # /tmp/d20151112-27349-1nbyzx3/solution.rb:165:in `belote?'
     # /tmp/d20151112-27349-1nbyzx3/spec.rb:266:in `block (4 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  6) BeloteDeck hand #carre_of_jacks? behaves like carre-checking method returns true when there is a carre
     Failure/Error: expect(hand.public_send(method)).to be true
       
       expected #<TrueClass:20> => true
            got #<Fixnum:9> => 4
       
       Compared using equal?, which compares object identity,
       but expected and actual are not the same object. Use
       `expect(actual).to eq(expected)` if you don't care about
       object identity in this example.
     Shared Example Group: "carre-checking method" called from /tmp/d20151112-27349-1nbyzx3/spec.rb:386
     # /tmp/d20151112-27349-1nbyzx3/spec.rb:86:in `block (2 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  7) BeloteDeck hand #carre_of_jacks? behaves like carre-checking method returns false when there is no carre
     Failure/Error: expect(hand.public_send(method)).to be false
       
       expected #<FalseClass:0> => false
            got #<Fixnum:7> => 3
       
       Compared using equal?, which compares object identity,
       but expected and actual are not the same object. Use
       `expect(actual).to eq(expected)` if you don't care about
       object identity in this example.
     Shared Example Group: "carre-checking method" called from /tmp/d20151112-27349-1nbyzx3/spec.rb:386
     # /tmp/d20151112-27349-1nbyzx3/spec.rb:101:in `block (2 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  8) BeloteDeck hand #carre_of_nines? behaves like carre-checking method returns true when there is a carre
     Failure/Error: expect(hand.public_send(method)).to be true
       
       expected #<TrueClass:20> => true
            got #<Fixnum:9> => 4
       
       Compared using equal?, which compares object identity,
       but expected and actual are not the same object. Use
       `expect(actual).to eq(expected)` if you don't care about
       object identity in this example.
     Shared Example Group: "carre-checking method" called from /tmp/d20151112-27349-1nbyzx3/spec.rb:390
     # /tmp/d20151112-27349-1nbyzx3/spec.rb:86:in `block (2 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  9) BeloteDeck hand #carre_of_nines? behaves like carre-checking method returns false when there is no carre
     Failure/Error: expect(hand.public_send(method)).to be false
       
       expected #<FalseClass:0> => false
            got #<Fixnum:7> => 3
       
       Compared using equal?, which compares object identity,
       but expected and actual are not the same object. Use
       `expect(actual).to eq(expected)` if you don't care about
       object identity in this example.
     Shared Example Group: "carre-checking method" called from /tmp/d20151112-27349-1nbyzx3/spec.rb:390
     # /tmp/d20151112-27349-1nbyzx3/spec.rb:101:in `block (2 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  10) BeloteDeck hand #carre_of_aces? behaves like carre-checking method returns true when there is a carre
     Failure/Error: expect(hand.public_send(method)).to be true
       
       expected #<TrueClass:20> => true
            got #<Fixnum:9> => 4
       
       Compared using equal?, which compares object identity,
       but expected and actual are not the same object. Use
       `expect(actual).to eq(expected)` if you don't care about
       object identity in this example.
     Shared Example Group: "carre-checking method" called from /tmp/d20151112-27349-1nbyzx3/spec.rb:394
     # /tmp/d20151112-27349-1nbyzx3/spec.rb:86:in `block (2 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  11) BeloteDeck hand #carre_of_aces? behaves like carre-checking method returns false when there is no carre
     Failure/Error: expect(hand.public_send(method)).to be false
       
       expected #<FalseClass:0> => false
            got #<Fixnum:7> => 3
       
       Compared using equal?, which compares object identity,
       but expected and actual are not the same object. Use
       `expect(actual).to eq(expected)` if you don't care about
       object identity in this example.
     Shared Example Group: "carre-checking method" called from /tmp/d20151112-27349-1nbyzx3/spec.rb:394
     # /tmp/d20151112-27349-1nbyzx3/spec.rb:101:in `block (2 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  12) SixtySixDeck behaves like a deck #to_s returns the names of the cards, each on its own line
     Failure/Error: expect(small_deck.to_s.strip).to eq "Ace of Spades\n9 of Clubs"
     NoMethodError:
       undefined method `strip' for #<Array:0x007f0633976b30>
     Shared Example Group: "a deck" called from /tmp/d20151112-27349-1nbyzx3/spec.rb:400
     # /tmp/d20151112-27349-1nbyzx3/spec.rb:68:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  13) SixtySixDeck hand #twenty? returns true for king and queen not of the trump suit
     Failure/Error: expect(hand.twenty?(:hearts)).to be true
     NoMethodError:
       undefined method `belote?' for KingsAndQueensMethods:Module
     # /tmp/d20151112-27349-1nbyzx3/solution.rb:239:in `twenty?'
     # /tmp/d20151112-27349-1nbyzx3/spec.rb:439:in `block (4 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  14) SixtySixDeck hand #twenty? returns false for king and queen of the trump suit
     Failure/Error: expect(hand.twenty?(:clubs)).to be false
     NoMethodError:
       undefined method `belote?' for KingsAndQueensMethods:Module
     # /tmp/d20151112-27349-1nbyzx3/solution.rb:239:in `twenty?'
     # /tmp/d20151112-27349-1nbyzx3/spec.rb:452:in `block (4 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  15) SixtySixDeck hand #twenty? returns false for hands without a king and queen of the same suit
     Failure/Error: expect(hand.twenty?(:hearts)).to be false
     NoMethodError:
       undefined method `belote?' for KingsAndQueensMethods:Module
     # /tmp/d20151112-27349-1nbyzx3/solution.rb:239:in `twenty?'
     # /tmp/d20151112-27349-1nbyzx3/spec.rb:465:in `block (4 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

Finished in 0.03923 seconds
57 examples, 15 failures

Failed examples:

rspec /tmp/d20151112-27349-1nbyzx3/spec.rb:67 # WarDeck behaves like a deck #to_s returns the names of the cards, each on its own line
rspec /tmp/d20151112-27349-1nbyzx3/spec.rb:67 # BeloteDeck behaves like a deck #to_s returns the names of the cards, each on its own line
rspec /tmp/d20151112-27349-1nbyzx3/spec.rb:220 # BeloteDeck hand #highest_of_suit returns the strongest card of the specified suit
rspec /tmp/d20151112-27349-1nbyzx3/spec.rb:239 # BeloteDeck hand #belote? returns true if there is a king and a queen of the same suit
rspec /tmp/d20151112-27349-1nbyzx3/spec.rb:254 # BeloteDeck hand #belote? returns false when there is no king and queen of the same suit
rspec /tmp/d20151112-27349-1nbyzx3/spec.rb:74 # BeloteDeck hand #carre_of_jacks? behaves like carre-checking method returns true when there is a carre
rspec /tmp/d20151112-27349-1nbyzx3/spec.rb:89 # BeloteDeck hand #carre_of_jacks? behaves like carre-checking method returns false when there is no carre
rspec /tmp/d20151112-27349-1nbyzx3/spec.rb:74 # BeloteDeck hand #carre_of_nines? behaves like carre-checking method returns true when there is a carre
rspec /tmp/d20151112-27349-1nbyzx3/spec.rb:89 # BeloteDeck hand #carre_of_nines? behaves like carre-checking method returns false when there is no carre
rspec /tmp/d20151112-27349-1nbyzx3/spec.rb:74 # BeloteDeck hand #carre_of_aces? behaves like carre-checking method returns true when there is a carre
rspec /tmp/d20151112-27349-1nbyzx3/spec.rb:89 # BeloteDeck hand #carre_of_aces? behaves like carre-checking method returns false when there is no carre
rspec /tmp/d20151112-27349-1nbyzx3/spec.rb:67 # SixtySixDeck behaves like a deck #to_s returns the names of the cards, each on its own line
rspec /tmp/d20151112-27349-1nbyzx3/spec.rb:429 # SixtySixDeck hand #twenty? returns true for king and queen not of the trump suit
rspec /tmp/d20151112-27349-1nbyzx3/spec.rb:442 # SixtySixDeck hand #twenty? returns false for king and queen of the trump suit
rspec /tmp/d20151112-27349-1nbyzx3/spec.rb:455 # SixtySixDeck hand #twenty? returns false for hands without a king and queen of the same suit

История (2 версии и 1 коментар)

Алекс обнови решението на 06.11.2015 23:06 (преди около 9 години)

+module RanksAndSuits
+ def standard_ranks
+ {
+ ace: 1, king: 2, queen: 3, jack: 4,
+ 10 => 5, 9 => 6, 8 => 7, 7 => 8, 6 => 9,
+ 5 => 10, 4 => 11, 3 => 12, 2 => 13,
+ }
+ end
+
+ def belote_ranks
+ { ace: 1, 10 => 2, king: 3, queen: 4, jack: 5, 9 => 6, 8 => 7, 7 => 8 }
+ end
+
+ def sixty_six_ranks
+ { ace: 1, 10 => 2, king: 3, queen: 4, jack: 5, 9 => 6 }
+ end
+
+ def card_suits
+ [:spades, :hearts, :diamonds, :clubs]
+ end
+end
+
+module KingsAndQueensMethods
+ def belote?(cards)
+ kings_queens = cards.find_all { |x| x.rank == :king or x.rank == :queen }
+ kings_queens.sort_by! { |x| [x.suit, belote_ranks[x.rank]] }
+ same_suit = -> (card_group) { card_group[0].suit == card_group[1].suit }
+ kings_queens.each_cons(2).any?(&same_suit)
+ end
+end
+
+class Card
+ def initialize(rank, suit)
+ @rank, @suit = rank, suit
+ end
+
+ attr_reader :rank
+ attr_reader :suit
+
+ def to_s
+ rank_to_s, suit_to_s = @rank.to_s, @suit.to_s
+ rank_to_s.capitalize + " of " + suit_to_s.capitalize
+ end
+
+ def ==(rs)
+ @rank == rs.rank and @suit == rs.suit
+ end
+end
+
+class Deck
+ include Enumerable, RanksAndSuits
+
+ def initialize(cards = nil)
+ @deal_cards_number = 26
+ @card_ranks = standard_ranks
+ initialize_cards(cards)
+ end
+
+ def each
+ @cards.each { |card| yield card }
+ end
+
+ def size
+ @cards.size
+ end
+
+ def draw_top_card
+ @cards.delete_at(0)
+ end
+
+ def draw_bottom_card
+ @cards.delete_at(-1)
+ end
+
+ def top_card
+ @cards.first
+ end
+
+ def bottom_card
+ @cards.last
+ end
+
+ def shuffle
+ @cards.shuffle!
+ end
+
+ def sort
+ @cards.sort_by! { |x| [x.suit.to_s, - @card_ranks[x.rank]] }.reverse!
+ end
+
+ def to_s
+ @cards.each { |card| card.to_s }
+ end
+
+ def deal
+ cards_to_be_dealt = @cards.shift(@deal_cards_number)
+ Hand.new(cards_to_be_dealt)
+ end
+
+ private
+
+ def initialize_cards(cards)
+ if cards.nil?
+ @cards = Array.new
+ rank_and_suit_combinations = @card_ranks.keys.product(card_suits)
+ rank_and_suit_combinations.each { |x| @cards << Card.new(x[0], x[1]) }
+ else
+ @cards = cards
+ end
+ end
+end
+
+class Hand
+ def initialize(card_array)
+ @cards = card_array
+ end
+
+ attr_reader :cards
+
+ def size
+ @cards.size
+ end
+end
+
+class WarDeck < Deck
+ def deal
+ WarHand.new(super.cards)
+ end
+end
+
+class WarHand < Hand
+ def play_card
+ @cards.delete_at(0)
+ end
+
+ def allow_face_up?
+ size <= 3
+ end
+end
+
+class BeloteDeck < Deck
+ def initialize(cards = nil)
+ @deal_cards_number = 8
+ @card_ranks = belote_ranks
+ initialize_cards(cards)
+ end
+
+ def deal
+ belote_card = -> (card) { belote_ranks.keys.include? card.rank }
+ BeloteHand.new(super.cards.find_all(&belote_card))
+ end
+end
+
+class BeloteHand < Hand
+ include RanksAndSuits
+
+ def highest_of_suit(suit)
+ same_suit_cards = cards.find_all { |x| x.suit == suit }
+ same_suit_card.min_by { |x| belote_ranks[x.rank] }
+ end
+
+ def belote?
+ KingsAndQueensMethods.belote?(cards)
+ end
+
+ def tierce?
+ consecutive_from_same_suit?(3)
+ end
+
+ def quarte?
+ consecutive_from_same_suit?(4)
+ end
+
+ def quint?
+ consecutive_from_same_suit?(5)
+ end
+
+ def four_of_a_kind?(rank)
+ cards.count { |card| card.rank == rank }
+ end
+
+ def carre_of_jacks?
+ four_of_a_kind?(:jack)
+ end
+
+ def carre_of_nines?
+ four_of_a_kind?(9)
+ end
+
+ def carre_of_aces?
+ four_of_a_kind?(:ace)
+ end
+
+ private
+
+ def consecutive_from_same_suit?(number_of_cards)
+ sorted_cards = cards.sort_by { |x| [x.suit, - belote_ranks[x.rank]] }
+
+ sorted_cards.each_cons(number_of_cards).any? do |card_group|
+ same_suit = card_group.all? { |card| card.suit == card_group[0].suit }
+ same_suit and consecutive_cards?(card_group)
+ end
+ end
+
+ def consecutive_cards?(card_group)
+ rank_plus_index = Array.new
+
+ card_group.each_with_index do |card, i|
+ rank_plus_index[i] = belote_ranks[card.rank] + i
+ end
+ rank_plus_index.uniq.length == 1
+ end
+end
+
+class SixtySixDeck < Deck
+ def initialize(cards = nil)
+ @card_ranks = sixty_six_ranks
+ @deal_cards_number = 6
+ initialize_cards(cards)
+ end
+
+ def deal
+ sixty_six_card = -> (card) { sixty_six_ranks.keys.include? card.rank }
+ SixtySixHand.new(super.cards.find_all(&sixty_six_card))
+ end
+end
+
+class SixtySixHand < Hand
+ def forty?(trump_suit)
+ trump_kings_and_queens = cards.find_all do |card|
+ card.suit == trump_suit and
+ (card.rank == :queen or card.rank == :king)
+ end
+ trump_kings_and_queens.size == 2
+ end
+
+ def twenty?(trump_suit)
+ KingsAndQueensMethods.belote?(cards) and (not forty?(trump_suit))
+ end
+end

Алекс обнови решението на 08.11.2015 22:46 (преди около 9 години)

module RanksAndSuits
def standard_ranks
{
ace: 1, king: 2, queen: 3, jack: 4,
10 => 5, 9 => 6, 8 => 7, 7 => 8, 6 => 9,
5 => 10, 4 => 11, 3 => 12, 2 => 13,
}
end
def belote_ranks
- { ace: 1, 10 => 2, king: 3, queen: 4, jack: 5, 9 => 6, 8 => 7, 7 => 8 }
+ {ace: 1, 10 => 2, king: 3, queen: 4, jack: 5, 9 => 6, 8 => 7, 7 => 8}
end
def sixty_six_ranks
- { ace: 1, 10 => 2, king: 3, queen: 4, jack: 5, 9 => 6 }
+ {ace: 1, 10 => 2, king: 3, queen: 4, jack: 5, 9 => 6}
end
def card_suits
[:spades, :hearts, :diamonds, :clubs]
end
end
module KingsAndQueensMethods
def belote?(cards)
kings_queens = cards.find_all { |x| x.rank == :king or x.rank == :queen }
kings_queens.sort_by! { |x| [x.suit, belote_ranks[x.rank]] }
same_suit = -> (card_group) { card_group[0].suit == card_group[1].suit }
kings_queens.each_cons(2).any?(&same_suit)
end
end
class Card
def initialize(rank, suit)
@rank, @suit = rank, suit
end
attr_reader :rank
attr_reader :suit
def to_s
rank_to_s, suit_to_s = @rank.to_s, @suit.to_s
rank_to_s.capitalize + " of " + suit_to_s.capitalize
end
def ==(rs)
@rank == rs.rank and @suit == rs.suit
end
end
class Deck
include Enumerable, RanksAndSuits
def initialize(cards = nil)
@deal_cards_number = 26
@card_ranks = standard_ranks
initialize_cards(cards)
end
def each
@cards.each { |card| yield card }
end
def size
@cards.size
end
def draw_top_card
@cards.delete_at(0)
end
def draw_bottom_card
@cards.delete_at(-1)
end
def top_card
@cards.first
end
def bottom_card
@cards.last
end
def shuffle
@cards.shuffle!
end
def sort
@cards.sort_by! { |x| [x.suit.to_s, - @card_ranks[x.rank]] }.reverse!
end
def to_s
@cards.each { |card| card.to_s }
end
def deal
- cards_to_be_dealt = @cards.shift(@deal_cards_number)
Hand.new(cards_to_be_dealt)
end
private
def initialize_cards(cards)
if cards.nil?
@cards = Array.new
rank_and_suit_combinations = @card_ranks.keys.product(card_suits)
rank_and_suit_combinations.each { |x| @cards << Card.new(x[0], x[1]) }
else
@cards = cards
end
end
+
+ def cards_to_be_dealt
+ @cards.shift(@deal_cards_number)
+ end
end
class Hand
def initialize(card_array)
@cards = card_array
end
attr_reader :cards
def size
@cards.size
end
end
class WarDeck < Deck
def deal
- WarHand.new(super.cards)
+ WarHand.new(cards_to_be_dealt)
end
end
class WarHand < Hand
def play_card
@cards.delete_at(0)
end
def allow_face_up?
size <= 3
end
end
class BeloteDeck < Deck
def initialize(cards = nil)
@deal_cards_number = 8
@card_ranks = belote_ranks
initialize_cards(cards)
end
def deal
- belote_card = -> (card) { belote_ranks.keys.include? card.rank }
- BeloteHand.new(super.cards.find_all(&belote_card))
+ BeloteHand.new(cards_to_be_dealt)
end
end
class BeloteHand < Hand
include RanksAndSuits
def highest_of_suit(suit)
same_suit_cards = cards.find_all { |x| x.suit == suit }
same_suit_card.min_by { |x| belote_ranks[x.rank] }
end
def belote?
KingsAndQueensMethods.belote?(cards)
end
def tierce?
consecutive_from_same_suit?(3)
end
def quarte?
consecutive_from_same_suit?(4)
end
def quint?
consecutive_from_same_suit?(5)
end
- def four_of_a_kind?(rank)
- cards.count { |card| card.rank == rank }
- end
-
def carre_of_jacks?
four_of_a_kind?(:jack)
end
def carre_of_nines?
four_of_a_kind?(9)
end
def carre_of_aces?
four_of_a_kind?(:ace)
end
private
def consecutive_from_same_suit?(number_of_cards)
sorted_cards = cards.sort_by { |x| [x.suit, - belote_ranks[x.rank]] }
sorted_cards.each_cons(number_of_cards).any? do |card_group|
same_suit = card_group.all? { |card| card.suit == card_group[0].suit }
same_suit and consecutive_cards?(card_group)
end
end
- def consecutive_cards?(card_group)
+ def consecutive_cards?(sorted_card_group)
rank_plus_index = Array.new
- card_group.each_with_index do |card, i|
+ sorted_card_group.each_with_index do |card, i|
rank_plus_index[i] = belote_ranks[card.rank] + i
end
rank_plus_index.uniq.length == 1
end
+
+ def four_of_a_kind?(rank)
+ cards.count { |card| card.rank == rank }
+ end
end
class SixtySixDeck < Deck
def initialize(cards = nil)
@card_ranks = sixty_six_ranks
@deal_cards_number = 6
initialize_cards(cards)
end
def deal
- sixty_six_card = -> (card) { sixty_six_ranks.keys.include? card.rank }
- SixtySixHand.new(super.cards.find_all(&sixty_six_card))
+ SixtySixHand.new(cards_to_be_dealt)
end
end
class SixtySixHand < Hand
def forty?(trump_suit)
trump_kings_and_queens = cards.find_all do |card|
card.suit == trump_suit and
(card.rank == :queen or card.rank == :king)
end
trump_kings_and_queens.size == 2
end
def twenty?(trump_suit)
KingsAndQueensMethods.belote?(cards) and (not forty?(trump_suit))
end
end