From: David Tran Date: 2007-03-14T05:15:37+09:00 Subject: Re: [QUIZ] SimFrost (#117) # http://davidtran.doublegifts.com/blog/?p=10 class SimFrost STATUS = [:VACUUM, :VAPOR, :ICE] attr_reader :ticks, :width, :height, :grid def initialize(width, height, vapor_chance=0.5) raise "width must be even and >= 2" unless (width % 2 == 0) && (width >= 2) raise "height must be even and >= 2" unless (height % 2 == 0) && (height >= 2) @width = width @height = height @grid = Array.new(@height) do Array.new(@width) { rand < vapor_chance ? :VAPOR : :VACUUM } end @grid[@height / 2][@width / 2] = :ICE @ticks = 0 end def tick shift unless (@ticks % 2 == 0) (0...@height).step(2) do |r| (0...@width).step(2) do |c| cells = [[r,c], [r,c+1], [r+1,c], [r+1,c+1]] if cells.any? { |y, x| @grid[y][x] == :ICE } cells.each { |y, x| @grid[y][x] = :ICE if @grid[y][x] == :VAPOR } else cells_rotate = rand(2).zero? \ ? [cells[2], cells[0], cells[3], cells[1]] \ : [cells[1], cells[3], cells[0], cells[2]] rotate_values = cells_rotate.map { |y,x| @grid[y][x] } cells.each_with_index { |(y,x), i| @grid[y][x] = rotate_values[i] } end end end unshift unless (@ticks % 2 == 0) @ticks = @ticks + 1 @grid end def done? not @grid.flatten.include?(:VAPOR) end private def shift @grid << @grid.shift @grid.each { |row| row << row.shift } end def unshift @grid.unshift(@grid.pop) @grid.each { |row| row.unshift(row.pop) } end end if __FILE__ == $0 if ARGV.size < 3 puts "Usage: #$0 gif_file_name width height [vapor_chance]" exit end file_name = ARGV[0] width = ARGV[1].to_i height = ARGV[2].to_i vapor_chance = ARGV[3] ? ARGV[3].to_f : 0.5 require 'RMagick' ICE_COLOR = 'blue' imageList = Magick::ImageList.new simFrost = SimFrost.new(width, height, vapor_chance) while (not simFrost.done?) do image = Magick::Image.new(width, height) grid = simFrost.tick (0...height).each do |y| (0...width).each do |x| image.pixel_color(x, y, ICE_COLOR) if grid[y][x] == :ICE end end imageList << image end imageList.write(file_name) end