91 lines
1.8 KiB
Ruby
91 lines
1.8 KiB
Ruby
class Ant
|
|
|
|
class OutOfBoundsException < StandardError; end
|
|
|
|
class Plane
|
|
def initialize(x, y)
|
|
@size_x, @size_y = x, y
|
|
@cells = Array.new(y) {Array.new(x, :white)}
|
|
end
|
|
|
|
def white?(px, py)
|
|
@cells[py][px] == :white
|
|
end
|
|
|
|
def toggle_colour(px, py)
|
|
@cells[py][px] = (white?(px, py) ? :black : :white)
|
|
end
|
|
|
|
def check_bounds(px, py)
|
|
unless (0 <= px and px < @size_x) and (0 <= py and py < @size_y)
|
|
raise OutOfBoundsException, "(#@size_x, #@size_y)"
|
|
end
|
|
end
|
|
|
|
def to_s
|
|
@cells.collect {|row|
|
|
row.collect {|cell| cell == :white ? "." : "#"}.join + "\n"
|
|
}.join
|
|
end
|
|
end
|
|
|
|
dir_move = [[:north, [0,-1]], [:east, [1,0]], [:south, [0,1]], [:west, [-1,0]]]
|
|
Move = Hash[dir_move]
|
|
directions = dir_move.map{|dir, move| dir} # [:north, :east, :south, :west]
|
|
Right = Hash[ directions.zip(directions.rotate).to_a ]
|
|
Left = Right.invert
|
|
|
|
def initialize(size_x, size_y, pos_x=size_x/2, pos_y=size_y/2)
|
|
@plane = Plane.new(size_x, size_y)
|
|
@pos_x, @pos_y = pos_x, pos_y
|
|
@direction = :south
|
|
@plane.check_bounds(@pos_x, @pos_y)
|
|
end
|
|
|
|
def run
|
|
moves = 0
|
|
loop do
|
|
begin
|
|
moves += 1
|
|
move
|
|
rescue OutOfBoundsException
|
|
break
|
|
end
|
|
end
|
|
moves
|
|
end
|
|
|
|
def move
|
|
@plane.toggle_colour(@pos_x, @pos_y)
|
|
advance
|
|
if @plane.white?(@pos_x, @pos_y)
|
|
@direction = Right[@direction]
|
|
else
|
|
@direction = Left[@direction]
|
|
end
|
|
end
|
|
|
|
def advance
|
|
dx, dy = Move[@direction]
|
|
@pos_x += dx
|
|
@pos_y += dy
|
|
@plane.check_bounds(@pos_x, @pos_y)
|
|
end
|
|
|
|
def position
|
|
"(#@pos_x, #@pos_y)"
|
|
end
|
|
|
|
def to_s
|
|
@plane.to_s
|
|
end
|
|
end
|
|
|
|
#
|
|
# the simulation
|
|
#
|
|
ant = Ant.new(100, 100)
|
|
moves = ant.run
|
|
puts "out of bounds after #{moves} moves: #{ant.position}"
|
|
puts ant
|