Created
July 13, 2010 07:28
-
-
Save anonymous/473578 to your computer and use it in GitHub Desktop.
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
#I have included in this file the GameOfLife class as well as the supplied | |
#(but slightly modified) LifeNcurses class. See end of file for example of | |
#running a curses demonstration of my GameOfLife class. | |
#Thanks for running this challenge! | |
class GameOfLife | |
attr_accessor :state, :width, :height | |
def initialize(*size) | |
if (size.length == 2 && size[0].class == Fixnum && size[1].class == Fixnum) | |
#if passed 2 numbers, create a grid with those sizes | |
@width, @height = size[0], size[1] | |
elsif (size.length == 1 && size[0].class == Fixnum) | |
#if passed 1 number, create a square grid of that size | |
@width = @height = size[0] | |
elsif (size.all? {|i| i.class == Array} && size.map{|i| i.length}.uniq.length == 1) | |
#if passed a grid as an array, create that grid | |
#checks that all elements of size are arrays and are all of the same length | |
@state, @height, @width = size, size.length, size[0].length | |
return | |
else | |
#otherwise, create a 'standard' 5x5 grid | |
@width = 5 | |
@height = 5 | |
end | |
#Code to create grid array | |
@state = [] | |
@height.times do | |
arr = [] | |
@width.times {arr << rand(2)} | |
@state << arr | |
end | |
end | |
def evolve | |
#return the next generation of the game of life (via evolve_internal method) | |
evolve_internal | |
end | |
def evolve! | |
#return next generation and update state to next generation | |
@state = evolve_internal | |
end | |
protected | |
def evolve_internal | |
#generates new 2-dimensional array of dimensions @width x @height | |
#that is set to values of next generation of game of life | |
#by checking through existing state of game via cellcheck method | |
arr = [] | |
@height.times do |row| | |
row_array = [] | |
@width.times {|col| row_array << cellcheck(row,col)} | |
arr << row_array | |
end | |
arr | |
end | |
def cellcheck(row,col) | |
#For a cell at row,col checks each of the eight cells surrounding it and counts all of the live cells | |
#Uses check_for_border method to look across the edges of the game board | |
count = 0 | |
(-1..1).each do |row_offset| | |
(-1..1).each do |col_offset| | |
unless (row_offset == 0 && col_offset == 0) | |
row_to_check = check_for_border(row + row_offset,@height) | |
col_to_check = check_for_border(col + col_offset,@width) | |
count += 1 if (@state[row_to_check][col_to_check]) == 1 | |
end | |
end | |
end | |
return 0 if @state[row][col] == 1 && (count < 2 || count > 3) | |
return 1 if @state[row][col] == 1 && (count == 2 || count == 3) | |
return 1 if @state[row][col] == 0 && count == 3 | |
0 | |
end | |
def check_for_border(position,size) | |
position = size - 1 if position == -1 | |
position = 0 if position == size | |
position | |
end | |
end | |
require 'rubygems' | |
require 'ffi-ncurses' | |
class LifeNcurses | |
# spaces from the border of the terminal | |
MARGIN = 2 | |
include FFI::NCurses | |
def initialize(game_of_life,iterations=100) | |
@stdscr = initscr | |
cbreak | |
(1..iterations).each do |generation| | |
clear | |
display_title(generation) | |
show game_of_life.evolve! #modified to use evolve! method rather than evolve | |
end | |
ensure | |
endwin | |
end | |
def show(state) | |
state.each_with_index do |row,row_index| | |
row.each_with_index do |col, col_index| | |
mvwaddstr @stdscr, row_index+MARGIN, col_index+MARGIN, '#' if state[row_index][col_index] == 1 | |
end | |
end | |
refresh | |
sleep 1 | |
end | |
def display_title(generation) | |
mvwaddstr @stdscr, 0, 1, "Game of life: Generation #{generation}" | |
end | |
end | |
#Uncomment line below and run 'ruby game_of_life.rb' to see curses demonstration | |
#LifeNcurses.new(GameOfLife.new(50,10),20) |
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
# Rules | |
# each cell 2 possible states, life of death | |
# 8 neighbours | |
# - any life cell < 2 neighbours dies | |
# - any life cell > 3 neighbours dies | |
# - any live cell with 2 or 3 neighbours lives to next generation | |
# - any dead cell with exactly 3 live neighbours becomes a live cell | |
# first generation: apply pattern | |
# | |
### EXAMPLE ########################################################################################################## | |
# WRITE YOUR OWN TESTS, OF COURSE | |
# test-driven development is the best, this is just to show you how it should work (if it's not clear from rules) | |
# Plus varying parameters on initialization allows you to do cooler things, like play with different sizes, seeds, etc. | |
####################################################################################################################### | |
require File.join(File.dirname(__FILE__), 'game_of_life') | |
require 'rubygems' | |
require 'test/unit' | |
class GameOfLifeTest < Test::Unit::TestCase | |
def setup | |
@game = GameOfLife.new(3) | |
end | |
def test_should_kill_with_no_neighbours | |
@game.state = [[1,0,0],[0,0,0],[0,0,0]] | |
after = @game.evolve | |
assert_equal after[0][0], 0 | |
end | |
def test_should_kill_with_just_one_neighbour | |
@game.state = [[0,0,0],[1,0,0],[1,0,0]] | |
after = @game.evolve | |
assert_equal after[1][0], 0 | |
assert_equal after[2][0], 0 | |
end | |
def test_should_kill_with_more_than_3_neighbours | |
@game.state = [[1,1,1],[1,1,1],[1,1,1]] | |
after = @game.evolve | |
assert_equal after, [[0,0,0],[0,0,0],[0,0,0]] | |
end | |
def test_should_give_birth_if_3_neighbours | |
@game.state = [[1,0,0],[1,1,0],[0,0,0]] | |
after = @game.evolve | |
assert_equal after, [[1,1,1],[1,1,1],[1,1,1]] | |
end | |
def test_single_integer_parameter_creates_square_grid_of_that_size | |
grid = GameOfLife.new(10) | |
assert_equal grid.state.length, 10 | |
assert_equal grid.state.all? {|row| row.length == 10}, true | |
end | |
def test_two_integer_parameters_creates_rectangular_grid_of_those_sizes | |
grid = GameOfLife.new(6,8) | |
assert_equal grid.state.length, 8 | |
assert_equal grid.state.all? {|row| row.length == 6}, true | |
end | |
def test_passing_an_array_of_arrays_creates_that_grid | |
grid = GameOfLife.new([1,0,1,0],[0,1,0,1],[1,0,1,0],[0,1,0,1]) | |
assert_equal grid.state, [[1,0,1,0],[0,1,0,1],[1,0,1,0],[0,1,0,1]] | |
end | |
def test_r_pentomino | |
grid = GameOfLife.new([0,0,0,0,0],[0,0,1,1,0],[0,1,1,0,0],[0,0,1,0,0],[0,0,0,0,0]) | |
assert_equal grid.evolve, [[0,0,0,0,0],[0,1,1,1,0],[0,1,0,0,0],[0,1,1,0,0],[0,0,0,0,0]] | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment