Skip to content

Instantly share code, notes, and snippets.

@davidpaulhunt
Created April 9, 2014 11:53
Show Gist options
  • Save davidpaulhunt/10260193 to your computer and use it in GitHub Desktop.
Save davidpaulhunt/10260193 to your computer and use it in GitHub Desktop.
Conway's Game of Life w/ rspec test script
class World
attr_reader :cells, :cells_with_neighbors, :cells_that_should_live, :cells_that_should_die
# [
# [cell cell cell],
# [cell cell cell],
# [cell cell cell]
# ]
def initialize
@cells = Array.new(25) { Array.new(25) { Cell.new } }
@cells_that_should_live = []
@cells_that_should_die = []
play_game
end
def locate_cells_and_neighbors
@cells_with_neighbors = []
@cells.each_with_index do |cell_row, row|
cell_row.each_with_index do |cell, column|
live_or_die(cell, row, column)
end
end
end
def find_neighbors(row, column)
neighbors = []
neighbors << cells[row][column + 1] rescue nil
neighbors << cells[row + 1][column + 1] rescue nil
neighbors << cells[row + 1][column] rescue nil
neighbors << cells[row + 1][column - 1] rescue nil
neighbors << cells[row - 1][column - 1] rescue nil
neighbors << cells[row - 1][column] rescue nil
neighbors << cells[row][column - 1] rescue nil
neighbors << cells[row - 1][column + 1] rescue nil
neighbors.compact!
return neighbors
end
def find_living_neighbors(cell, row, column)
find_neighbors(row, column).select { |cell| cell.alive }.length
end
def live_or_die(cell, row, column)
total = find_living_neighbors(cell, row, column)
case cell.alive
when true
if total == 2 || total == 3
@cells_that_should_live << cell
else
@cells_that_should_die << cell
end
when false
if total >= 3
@cells_that_should_live << cell
else
@cells_that_should_die << cell
end
end
end
def kill_doomed_cells
@cells_that_should_die.each do |cell|
cell.die
end
@cells_that_should_die.clear
end
def resurrect_lucky_cells
@cells_that_should_live.each do |cell|
cell.resurrect
end
@cells_that_should_live.clear
end
def move_to_next_generation
kill_doomed_cells
resurrect_lucky_cells
end
def print_world
system 'clear'
@cells.each do |ary|
ary.each do |cell|
if cell.alive == true
print "O "
else
print "- "
end
end
print "\n"
end
end
def play_game
birth_random_cells
print_world
sleep(1)
while 1 < 2
locate_cells_and_neighbors
move_to_next_generation
print_world
sleep(1)
end
end
def birth_random_cells
lottery = rand(0..99)
lottery.times do
row = rand(0..9)
col = rand(0..9)
@cells[row][col].resurrect
end
end
end
class Cell
attr_accessor :alive # => attr_reader
def initialize
self.alive = false # => @alive = false
end
def resurrect
self.alive = true # => @alive = true
end
def die
self.alive = false # => @alive = false
end
end
World.new
require 'rspec'
require './game_of_life_class.rb'
system "clear"
#### Testing the code ####
#world testing
describe World do
let(:world) { World.new } # create world instance
it 'should exist' do
world.should_not eq(nil) # ensure world exists
end
it 'should contain cells' do # make sure cells[] has cells
world.cells.should_not be_empty
end
it 'should contain 625 cells' do # make sure cells[] has 100 cells
world.cells.flatten.length.should eq(625)
# flatten makes 3d array 2d
end
it 'should identify cell neighbors' do
cell = world.cells.flatten.first
# makes array flat, grabs first element
world.locate_cells_and_neighbors.should_not eq(nil)
end
it 'should identify cells that should live' do
world.locate_cells_and_neighbors
world.cells_that_should_live.should_not be_empty
end
it 'should identify cells that should die' do
world.locate_cells_and_neighbors
world.cells_that_should_die.should_not be_empty
end
it 'should kill doomed cells' do
cell = Cell.new
cell.alive = true
world.cells_that_should_die << cell
world.kill_doomed_cells
cell.alive.should_not eq(true)
end
it 'should resurrect lucky cells' do
cell = Cell.new
cell.alive = false
world.cells_that_should_live << cell
world.resurrect_lucky_cells
cell.alive.should_not eq(false)
end
it 'should show entire world' do
world.print_world.should_not eq(nil)
end
end
# cell testing
describe Cell do
let(:cell) { Cell.new }
context 'dead cell' do
# ^^ tell yourself what the context of the test is
it 'should exist' do
cell.should_not eq(nil)
end
it 'should be dead' do
cell.alive.should eq(false)
end
it 'should resurrect' do
cell.resurrect
cell.alive.should eq(true)
end
end
context "living cell" do # if the cell is alive
before do # create a cell instance, set it to alive
# cell = Cell.new
cell.alive = true
end
it 'should die' do # does it die
cell.die # kill it with .die
cell.alive.should eq(false) # should eq false
end
end
end
Before running the test, you need to comment out the clear methods being run on both the cells_that_should_live and cells_that_should_die array, otherwise it will fail due to the empty values.
@switzersc
Copy link

live_or_die(cell, row, column) looks pretty similar to my example from basecamp...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment