ヒットアンドブローのスクリプトができた

でもひどいコードかも。。
ヒットアンドブローは、コンピュータの用意した数字の並びを当てるゲーム。
コンピュータは、こちらが考えた数字の並びと自分のものを比較して、
次の2つのヒントをくれる。

  • HIT: 数字も場所も合っているものの数
  • BLOW: 数字は合っているが場所は合っていないものの数

例えば、コンピュータの用意した数字の並びが4278で、
プレイヤーが考えた数字が4321だったときは、HIT:1 BLOW:1となる。
全部をHITにできれば勝ち。
また、今回は同じ数字を使ってもいいようにしてみた。
(そのせいで手こずった・・・。)

=begin
ヒットアンドブロー

<概要>
コンピュータの用意した数字の並びと同じ数字の並びをつくれば勝ち
HIT: 数字も場所も合っている
BLOW: 数字は合っているが場所は合っていない

<usage>
  > ruby hit-and-blow.rb [size]
  [size]でいくつの数字の並びなのかを指定できる(デフォルトは4)
=end


# 複数の数字の管理をする
class Numbers
  def initialize(size = 4)
    @size = size.to_i
    @numbers = Array.new # コンピュータの用意する数字の並び

    @size.times{
      @numbers << rand(10)
    }
  end
  
  # カードの表示
  def disp
    puts "com> #{@numbers}"
  end

  # コンピュータの用意した数字の並びとプレイヤーの数字の並びを比較する
  def compare(ply)
    # コンピュータとプレイヤーの用意した各数字の間にリンクを考える
    # 対応する数字同士はリンクする
    links = Array.new
    @size.times{
      link = Hash.new
      link['to'] = nil
      link['type'] = nil

      links << link
    }
    
    @size.times{|c|
      @size.times{|p|
        # toがpで、typeがhitのLinkが存在する場合はply[p]をパス
        next if links.detect{|l| l['to'] == p and l['type'] == 'hit'}
        
        if @numbers[c] == ply[p].to_i
          links[c]['to'] = p

          if c == p
            if l = links.detect{|l| l['to'] == p and l['type'] == 'blow'}
              l['to'] = l['type'] = nil
            end
                            
            links[c]['type'] = 'hit'
            break # 'hit'が分かったら、そのcom[c]の処理は終了
          else
            links[c]['type'] = 'blow'
          end
        end
      }
    }

    hit = blow = 0
    links.each{|l|
      hit += 1 if l['type'] == 'hit'
      blow += 1 if l['type'] == 'blow'
    }

    puts "  HIT:#{hit} BLOW:#{blow}"
    
    if hit == @size
      puts "Congratution!!"
      exit
    end
  end
end


size = ARGV.shift || 4
com = Numbers.new(size)
puts "#{size}つのランダムな数字の並びを当ててください。"

loop{ 
  print "ply> "
  line = gets
  line.chomp!
  exit if /^e/ =~ line
  com.disp if /^d/ =~ line
  com = Numbers.new if /^r/ =~ line
  unless /^\d{#{size}}$/ =~ line
    puts "#{size}つの数字を指定してください。"
    next
  end
  
  ply = line.split(//) # プレイヤーの用意する数字の並び
                       # 比較のために配列にする必要がある
  com.compare(ply)
}


今回、僕は自分で思っているよりもプログラムが書けないことに気づいた。
もっと色々自分で考えて書いてみないとダメだと思った。
だからもっと色々自分で考えて書いてみようと思う。