class HanoiTower::Game

Public Class Methods

new(size) click to toggle source
# File lib/hanoi_tower/game.rb, line 5
def initialize(size)
  @generation = 0
  @size = size
  @stick_size = @size * 2
  @towers = [
    Tower.new(@size),
    Tower.new(0),
    Tower.new(0)
  ]
  @smallest_ring_direction = @size.odd? ? 1 : -1
  @last_smallest_ring_stick = @smallest_ring_direction
end

Public Instance Methods

done?() click to toggle source

リングがどっか別のタワーに動かし終わった?

# File lib/hanoi_tower/game.rb, line 90
def done?
  @towers.drop(1).any? { |tower| tower.rings.size == @size }
end
next() click to toggle source
# File lib/hanoi_tower/game.rb, line 32
def next
  @generation += 1

  if @generation.odd?
    # 一番小さいリングを動かす
    # 一番小さいリングは必ず動かせる
    next_tower_for_smallest_ring.push(tower_having_smallest.pop)
    @last_smallest_ring_stick = @last_smallest_ring_stick + @smallest_ring_direction
  else
    # 一番小さいリング以外を動かす
    @towers.each { |tower, index|
      next if tower_having_smallest == tower

      moved = search_and_move(tower, others(tower))

      if moved
        return
      end
    }
  end
end
next_tower_for_smallest_ring() click to toggle source
# File lib/hanoi_tower/game.rb, line 26
def next_tower_for_smallest_ring
  # 一番小さいリングが次に動くべきタワーを返す
  # リングのサイズが奇数の時と偶数の時で動く方向が違う
  @towers[@last_smallest_ring_stick % @towers.size]
end
others(me) click to toggle source
# File lib/hanoi_tower/game.rb, line 18
def others(me)
  @towers.reject {|t| t === me}
end
print() click to toggle source
search_and_move(target_tower, other_towers) click to toggle source
# File lib/hanoi_tower/game.rb, line 54
def search_and_move(target_tower, other_towers)
  moving_ring = target_tower.rings.pop
  return nil if moving_ring.nil?

  other_towers.each {|tower|
    if tower.can_push?(moving_ring)
      tower.push(moving_ring)
      return true
    end
  }

  # 入れ替えなし。元に戻す
  target_tower.push(moving_ring)

  nil
end
to_s() click to toggle source
# File lib/hanoi_tower/game.rb, line 75
def to_s
  string = "#{@generation} times\n"
  @towers.each { |tower|
    if tower.rings.empty?
      string << '-' * (@stick_size)
      string << "\n"
    else
      string << tower.rings.map(&:to_s).join('-').ljust(@stick_size, '-')
      string << "\n"
    end
  }
  string
end
tower_having_smallest() click to toggle source
# File lib/hanoi_tower/game.rb, line 22
def tower_having_smallest
  @towers.find { |tower| tower.rings.last&.size == 1 }
end