Created
November 4, 2011 17:54
-
-
Save marksim/1340006 to your computer and use it in GitHub Desktop.
Game of Life with Rspec
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'rspec' | |
class Cell | |
attr_accessor :x, :y, :world | |
def initialize(world, x=0, y=0) | |
@world = world | |
@x = x; @y = y | |
@world.add(self) | |
end | |
def neighbors | |
@world.neighbors_of(@x, @y) | |
end | |
def die | |
@world.cells.delete(self) | |
end | |
end | |
class World | |
attr_accessor :cells | |
def initialize | |
@cells = [] | |
end | |
def self.load(coord_array) | |
coord_array.each do |x, y| | |
Cell.new(self, x, y) | |
end | |
end | |
def neighbors_of(x, y) | |
@cells.select {|c| c.x == x-1 || c.x == x+1 || c.x == x}. | |
select {|c| c.y == y-1 || c.y == y+1 || c.y == y }. | |
reject {|c| c.x == x && c.y == y} | |
end | |
def dead_near(x, y) | |
dead = [] | |
(x-1..x+1).each do |x_coord| | |
(y-1..y+1).each do |y_coord| | |
dead << [x_coord, y_coord] if cell_at(x_coord, y_coord).nil? | |
end | |
end | |
dead | |
end | |
def add(cell) | |
@cells << cell if cell_at(cell.x, cell.y).nil? | |
end | |
def cell_at(x, y) | |
@cells.select {|c| c.x == x && c.y == y}.first | |
end | |
def tick | |
dying = [] | |
birthing = [] | |
@cells.each do |cell| | |
dying << cell if cell.neighbors.count < 2 | |
dying << cell if cell.neighbors.count > 3 | |
dead_near(cell.x, cell.y).each do |dx, dy| | |
birthing << [dx, dy] if neighbors_of(dx, dy).count == 3 | |
end | |
end | |
dying.each(&:die) | |
birthing.each do |x, y| | |
Cell.new(self, x, y) | |
end | |
end | |
end | |
describe Cell do | |
let(:world) { World.new } | |
context "generally" do | |
subject { Cell.new(world) } | |
it "creates a cell " do | |
subject.should be_a Cell | |
end | |
it "creates a cell at given coordinates" do | |
c = Cell.new(world, 1, 3) | |
c.x.should == 1 | |
c.y.should == 3 | |
end | |
it "registers itself with a world" do | |
c = Cell.new(world, 5, 4) | |
world.cells.should include c | |
end | |
it "knows it has no neighbors" do | |
subject.neighbors.count.should == 0 | |
end | |
it "knows it has one neighbor north of it" do | |
cell = Cell.new(world, 0, 1) | |
subject.neighbors.count.should == 1 | |
end | |
it "knows it has one neighbor east of it" do | |
cell = Cell.new(world, 1, 0) | |
subject.neighbors.count.should == 1 | |
end | |
it "knows it has one neighbor south of it" do | |
cell = Cell.new(world, 0, -1) | |
subject.neighbors.count.should == 1 | |
end | |
it "knows it has one neighbor west of it" do | |
cell = Cell.new(world, -1, 0) | |
subject.neighbors.count.should == 1 | |
end | |
it "knows it has one neighbor northeast of it" do | |
cell = Cell.new(world, 1, 1) | |
subject.neighbors.count.should == 1 | |
end | |
it "knows it has one neighbor northwest of it" do | |
cell = Cell.new(world, -1, 1) | |
subject.neighbors.count.should == 1 | |
end | |
it "knows it has one neighbor southeast of it" do | |
cell = Cell.new(world, 1, -1) | |
subject.neighbors.count.should == 1 | |
end | |
it "knows it has one neighbor southwest of it" do | |
cell = Cell.new(world, -1, -1) | |
subject.neighbors.count.should == 1 | |
end | |
end | |
context "dies off when ticked if fewer than 2 neighbors" do | |
let(:world) { World.new } | |
it "dies off when it has 0 neighbors" do | |
c = Cell.new(world, 1, 1) | |
world.cells.should include c | |
world.tick | |
world.cells.should_not include c | |
end | |
it "dies off when it has 1 neighbors" do | |
Cell.new(world, 1, 2) | |
c = Cell.new(world, 1, 1) | |
world.cells.should include c | |
world.tick | |
world.cells.should_not include c | |
end | |
end | |
context "lives on when ticked if 2 or 3 neighbors" do | |
it "lives when it has 2 neighbors" do | |
Cell.new(world, 1, 2) | |
Cell.new(world, 2, 1) | |
c = Cell.new(world, 1, 1) | |
world.cells.should include c | |
world.tick | |
world.cells.should include c | |
end | |
it "lives when it has 3 neighbors" do | |
Cell.new(world, 1, 2) | |
Cell.new(world, 2, 1) | |
Cell.new(world, -1, 2) | |
c = Cell.new(world, 1, 1) | |
world.cells.should include c | |
world.tick | |
world.cells.should include c | |
end | |
end | |
context "dies off when ticked if more than 3 neighbors" do | |
it "dies when it has 4 neighbors" do | |
Cell.new(world, -1, -1) | |
Cell.new(world, -1, 0) | |
Cell.new(world, -1, 1) | |
Cell.new(world, 0, -1) | |
c = Cell.new(world, 0, 0) | |
world.cells.should include c | |
world.tick | |
world.cells.should_not include c | |
end | |
it "dies when it has 5 neighbors" do | |
Cell.new(world, -1, -1) | |
Cell.new(world, -1, 0) | |
Cell.new(world, -1, 1) | |
Cell.new(world, 0, -1) | |
Cell.new(world, 0, 1) | |
c = Cell.new(world, 0, 0) | |
world.cells.should include c | |
world.tick | |
world.cells.should_not include c | |
end | |
it "dies when it has 6 neighbors" do | |
Cell.new(world, -1, 1) | |
Cell.new(world, -1, 0) | |
Cell.new(world, -1, 1) | |
Cell.new(world, 0, -1) | |
Cell.new(world, 0, 1) | |
Cell.new(world, 1, -1) | |
c = Cell.new(world, 0, 0) | |
world.cells.should include c | |
world.tick | |
world.cells.should_not include c | |
end | |
it "dies when it has 7 neighbors" do | |
Cell.new(world, -1, 1) | |
Cell.new(world, -1, 0) | |
Cell.new(world, -1, 1) | |
Cell.new(world, 0, -1) | |
Cell.new(world, 0, 1) | |
Cell.new(world, 1, -1) | |
Cell.new(world, 1, 0) | |
c = Cell.new(world, 0, 0) | |
world.cells.should include c | |
world.tick | |
world.cells.should_not include c | |
end | |
it "dies when it has 8 neighbors" do | |
Cell.new(world, -1, 1) | |
Cell.new(world, -1, 0) | |
Cell.new(world, -1, 1) | |
Cell.new(world, 0, -1) | |
Cell.new(world, 0, 1) | |
Cell.new(world, 1, -1) | |
Cell.new(world, 1, 0) | |
Cell.new(world, 1, 1) | |
c = Cell.new(world, 0, 0) | |
world.cells.should include c | |
world.tick | |
world.cells.should_not include c | |
end | |
end | |
context "reproduces if exactly 3 neighbors" do | |
it "does not reproduce with 2 neighbors" do | |
Cell.new(world, 1, -1) | |
Cell.new(world, 1, 0) | |
world.tick | |
world.cell_at(0, 0).should be_nil | |
end | |
it "does reproduce with 3 neighbors" do | |
Cell.new(world, 1, -1) | |
Cell.new(world, 1, 0) | |
Cell.new(world, 0, 1) | |
world.tick | |
world.cell_at(0, 0).should_not be_nil | |
end | |
it "does not reproduce with 4 neighbors" do | |
Cell.new(world, 0, 1) | |
Cell.new(world, 0, -1) | |
Cell.new(world, -1, 0) | |
Cell.new(world, 1, 0) | |
world.tick | |
world.cell_at(0, 0).should be_nil | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment