DZone Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

Snippets has posted 5883 posts at DZone. View Full User Profile

Silly Game Of War

09.05.2006
| 2427 views |
  • submit to reddit
        
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