class Card
include Comparable
attr_accessor :suit, :value
@@values = Hash.new { |hash, key| key.to_s }
@@values.merge!(11 => 'jack', 12 => 'queen', 13 => 'king', 14 => 'ace')
def initialize(suit, value)
@suit = suit
@value = value
end
def to_s
"#{@@values[@value]} of #{@suit}s"
end
def <=> (other)
@value <=> other.value
end
end
class GroupOfCards < Array
def shuffle!
replace(sort_by { rand })
end
def to_s
join(", ")
end
end
class Deck < GroupOfCards
def initialize
[:spade, :diamond, :club, :heart].each do |suit|
(2..14).each do |value|
push(Card.new(suit, value))
end
end
end
end
class Player
attr_accessor :name, :table
def initialize(name)
@name = name
@hand = GroupOfCards.new
@pile = GroupOfCards.new
@table = GroupOfCards.new
end
def play_card
if @hand.empty?
@hand, @pile = @pile, @hand
@hand.shuffle!
end
@table << @hand.pop
end
def add_card(card)
@pile << card
end
def cards
@hand + @pile
end
def showing
@table.last
end
def card_count
@hand.size + @pile.size + @table.size
end
def has_cards?
card_count > 0
end
def status
"#{@name}(#{card_count}) plays #{showing}"
end
def to_s
name
end
end
class GameOfWar
def initialize(player_count=2)
deck = Deck.new
deck.shuffle!
@players = Array.new(player_count) { |i| Player.new("Player #{i+1}") }
deck.shuffle!
until deck.empty?
player = @players.shift
player.add_card(deck.pop)
@players.push(player)
end
end
def play_round(players)
spoils_of_war = []
players.each do |p|
p.play_card
puts p.status
end
winners = players.sort_by { |p| p.showing }
high_card = winners.last.showing
winners = winners.select { |p| p.showing == high_card }
if winners.size > 1
puts "WAR: #{winners.join(", ")}"
winners.each { |p| p.play_card }
winner = play_round(winners)
else
winner = winners.first
puts "Winner: #{winner}"
end
players.each { |p| spoils_of_war += p.table; p.table = [] }
spoils_of_war.each { |c| winner.add_card(c) }
winner
end
def play
round = 1
until @players.size == 1
puts "\nAt Round #{round}"
play_round(@players)
round += 1
loosers = @players.select { |p| p.card_count == 0 }
loosers.each { |p| puts "#{p} lost"}
@players -= loosers
end
puts "\n#{@players.first.name} Won!!!"
end
def to_s
@players.join("\n")
end
end
if __FILE__ == $0
g = GameOfWar.new 3
g.play
end