Task

Implement the classic children's game Rock-paper-scissors, as well as a simple predictive   AI   (artificial intelligence)   player.

Rock Paper Scissors is a two player game.

Each player chooses one of rock, paper or scissors, without knowing the other player's choice.

The winner is decided by a set of rules:

   Rock beats scissors
   Scissors beat paper
   Paper beats rock


If both players choose the same thing, there is no winner for that round.

For this task, the computer will be one of the players.

The operator will select Rock, Paper or Scissors and the computer will keep a record of the choice frequency, and use that information to make a weighted random choice in an attempt to defeat its opponent.



Extra credit

Support additional choices   additional weapons.




class RockPaperScissorsGame
  CHOICES = %w[rock paper scissors quit]
  BEATS = {
    'rock'     => 'paper',
    'paper'    => 'scissors',
    'scissors' => 'rock',
  }
 
  def initialize()
    @plays = {
      'rock'     => 1,
      'paper'    => 1,
      'scissors' => 1,
    }
    @score = [0, 0, 0]          # [0]:Human wins, [1]:Computer wins, [2]:draw
 
    play
  end
 
  def humanPlay
    loop do
      print "\nYour choice: #{CHOICES}? "
      answer = STDIN.gets.strip.downcase
      next if answer.empty?
      idx = CHOICES.find_index {|choice| choice.match(/^#{answer}/)}
      return CHOICES[idx] if idx
      puts "invalid answer, try again"
    end
  end
 
  def computerPlay
    total = @plays.values.reduce(:+)
    r = rand(total) + 1
    sum = 0
    CHOICES.each do |choice|
      sum += @plays[choice]
      return BEATS[choice] if r <= sum
    end
  end
 
  def play
    loop do
      h = humanPlay
      break if h == "quit"
      c = computerPlay
      print "H: #{h}, C: #{c} => "
 
      # only update the human player's history after the computer has chosen
      @plays[h] += 1
 
      if h == c
        puts "draw"
        @score[2] += 1
      elsif h == BEATS[c]
        puts "Human wins"
        @score[0] += 1
      else
        puts "Computer wins"
        @score[1] += 1
      end
      puts "score: human=%d, computer=%d, draw=%d" % [*@score]
    end
    @plays.each_key{|k| @plays[k] -= 1}
    puts "\nhumans chose #{@plays}"
  end
end
 
RockPaperScissorsGame.new