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 = [] # get cards players.each do |p| p.play_card puts p.status end # find winner (handle ties) winners = players.sort_by { |p| p.showing } high_card = winners.last.showing winners = winners.select { |p| p.showing == high_card } # deal with ties if winners.size > 1 puts "WAR: #{winners.join(", ")}" # put one card "in the kitty" 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 # check for loosers 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
You need to create an account or log in to post comments to this site.