Skip to content

Instantly share code, notes, and snippets.

@benzittlau
Created September 24, 2012 16:06
Show Gist options
  • Save benzittlau/3776742 to your computer and use it in GitHub Desktop.
Save benzittlau/3776742 to your computer and use it in GitHub Desktop.
Game of life implementation in ruby
class World
attr_accessor :cells
NEXT_STATE = [:dead, :alive, :alive, :dead, :dead, :dead, :dead, :dead]
def initialize(cells)
@cells = cells
end
def add_newly_born_cells
@cells.each do |cell|
(-1..1).each do |x_offset|
(-1..1).each do |y_offset|
x = cell[:x] + x_offset
y = cell[:y] + y_offset
if neighbour_count(x,y) == 3
@next_cell_generation.add({:x => x, :y => y})
end
end
end
end
end
def kill_dying_cells
@next_cell_generation.each do |cell|
if World::NEXT_STATE[(neighbour_count cell[:x], cell[:y]) - 1] == :dead
@next_cell_generation.delete(cell)
end
end
end
def evolve
@next_cell_generation = @cells.clone
kill_dying_cells
add_newly_born_cells
@cells = @next_cell_generation
end
def neighbour_count(x, y)
get_neighbours(x,y).count
end
def get_neighbours(x,y)
@cells.select {|cell| (cell[:x].between?(x-1, x+1) && cell[:y].between?(y-1, y+1)) && cell != {:x => x, :y => y} }
end
end
# bowling_spec.rb
require './world'
describe World, "#evolve" do
describe "no live cells" do
before(:each) do
@world = World.new(Set.new)
end
it "should return empty world after one turn" do
@world.evolve
@world.cells.count.should eq(0)
end
end
describe "one live cell" do
before(:each) do
@world = World.new Set.new([{:x => 0, :y => 0}])
end
it "should return empty world after one turn" do
@world.evolve
@world.cells.count.should eq(0)
end
end
describe "two live cells" do
before(:each) do
@world = World.new Set.new([{:x => 0, :y => 0}, {:x => 0, :y => 1}])
end
it "should return empty world after one turn" do
@world.evolve
@world.cells.count.should eq(0)
end
end
describe "a block of cells" do
before(:each) do
@cell_block = Set.new([{:x => 0, :y => 0},
{:x => 0, :y => 1},
{:x => 1, :y => 0},
{:x => 1, :y => 1}])
@world = World.new(@cell_block)
end
it "should return a matching block of cells" do
@world.evolve
@cell_block.each do |cell|
@world.cells.should include cell
end
@world.cells.count.should eq @cell_block.count
end
end
describe "five live cells" do
before(:each) do
# X
# XX
# XX
@cell_block = Set.new([{:x => 0, :y => 0},
{:x => 0, :y => 1},
{:x => 1, :y => 0},
{:x => 1, :y => 1},
{:x => 1, :y => 2}])
@world = World.new(@cell_block)
end
it "should return five live cells" do
# XX
# X
# XX
@world.evolve
@world.cells.count.should eq 5
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment