How to resolve the algorithm Conway's Game of Life step by step in the Ruby programming language
How to resolve the algorithm Conway's Game of Life step by step in the Ruby programming language
Table of Contents
Problem Statement
The Game of Life is a cellular automaton devised by the British mathematician John Horton Conway in 1970. It is the best-known example of a cellular automaton. Conway's game of life is described here: A cell C is represented by a 1 when alive, or 0 when dead, in an m-by-m (or m×m) square array of cells. We calculate N - the sum of live cells in C's eight-location neighbourhood, then cell C is alive or dead in the next generation based on the following table: Assume cells beyond the boundary are always dead. The "game" is actually a zero-player game, meaning that its evolution is determined by its initial state, needing no input from human players. One interacts with the Game of Life by creating an initial configuration and observing how it evolves.
Although you should test your implementation on more complex examples such as the glider in a larger universe, show the action of the blinker (three adjoining cells in a row all alive), over three generations, in a 3 by 3 grid.
Let's start with the solution:
Step by Step solution about How to resolve the algorithm Conway's Game of Life step by step in the Ruby programming language
This Ruby code provides an implementation of John Conway's Game of Life, a cellular automation simulation. It defines two classes, Game
and GameBoard
, to model the game and its board, respectively. The Cell
class represents individual cells on the board.
-
game_of_life
Function:- Defines a method to run the Game of Life simulation.
- Takes parameters such as
name
(board name),size
(board dimensions),generations
(number of simulation steps), andinitial_life
(initial seed points).
-
new_board
Function:- Generates a new rectangular board of zeros with specified dimensions.
-
seed
Function:- Randomly or manually seeds the board with living cells (
value
set to 1).
- Randomly or manually seeds the board with living cells (
-
evolve
Function:- Evolves the board according to the Game of Life rules.
- Iterates over each cell and calculates its fate based on its neighbors.
-
fate
Function:- Determines the fate of a cell based on the number of living neighbors.
- A cell becomes alive if it has 3 living neighbors or if it's currently alive and has 2 living neighbors.
-
barren?
Function:- Checks if the board has any living cells.
-
print_board
Function:- Prints the current state of the board, showing living cells as '#' and dead cells as '.'.
-
Game
Class:- Encapsulates the game logic and board state.
- Initializes with parameters similar to the
game_of_life
function.
-
evolve
Method (inGame
Class:- Evolves the board and returns a new
GameBoard
instance.
- Evolves the board and returns a new
-
cell_fate
Method (inGame
Class:
- Calculates the fate of a cell based on its neighbors.
-
GameBoard
Class:- Represents the game board.
- Contains an array of
Cell
objects.
-
seed_board
Method (inGameBoard
Class:- Seeds the board with living cells.
-
each_index
Method (inGameBoard
Class:- Iterates over the indices of the board.
-
==
Method (inGameBoard
Class:- Compares two
GameBoard
instances for equality based on their living cells.
- Compares two
-
barren?
Method (inGameBoard
Class:- Checks if the board has any living cells.
-
life
Method (inGameBoard
Class:- Returns an array of the coordinates of living cells.
-
display
Method (inGameBoard
Class:- Prints the board state, similar to the
print_board
function.
- Prints the board state, similar to the
-
apocalypse
Method (inGameBoard
Class:- Clears the board by setting all cells to dead.
-
Cell
Class:- Represents an individual cell on the board.
- Has properties like
alive?
andvalue
(0 for dead, 1 for alive).
The code provides two ways to play the game: the original game_of_life
function and the object-oriented approach using the Game
class. It supports different board configurations, including "blinker," "glider," and "random." The program simulates the game for a specified number of generations or until the board becomes static or barren.
Source code in the ruby programming language
def game_of_life(name, size, generations, initial_life=nil)
board = new_board size
seed board, size, initial_life
print_board board, name, 0
reason = generations.times do |gen|
new = evolve board, size
print_board new, name, gen+1
break :all_dead if barren? new, size
break :static if board == new
board = new
end
if reason == :all_dead then puts "no more life."
elsif reason == :static then puts "no movement"
else puts "specified lifetime ended"
end
puts
end
def new_board(n)
Array.new(n) {Array.new(n, 0)}
end
def seed(board, n, points=nil)
if points.nil?
# randomly seed board
indices = []
n.times {|x| n.times {|y| indices << [x,y] }}
indices.shuffle[0,10].each {|x,y| board[y][x] = 1}
else
points.each {|x, y| board[y][x] = 1}
end
end
def evolve(board, n)
new = new_board n
n.times {|i| n.times {|j| new[i][j] = fate board, i, j, n}}
new
end
def fate(board, i, j, n)
i1 = [0, i-1].max; i2 = [i+1, n-1].min
j1 = [0, j-1].max; j2 = [j+1, n-1].min
sum = 0
for ii in (i1..i2)
for jj in (j1..j2)
sum += board[ii][jj] if not (ii == i and jj == j)
end
end
(sum == 3 or (sum == 2 and board[i][j] == 1)) ? 1 : 0
end
def barren?(board, n)
n.times {|i| n.times {|j| return false if board[i][j] == 1}}
true
end
def print_board(m, name, generation)
puts "#{name}: generation #{generation}"
m.each {|row| row.each {|val| print "#{val == 1 ? '#' : '.'} "}; puts}
end
game_of_life "blinker", 3, 2, [[1,0],[1,1],[1,2]]
game_of_life "glider", 4, 4, [[1,0],[2,1],[0,2],[1,2],[2,2]]
game_of_life "random", 5, 10
class Game
def initialize(name, size, generations, initial_life=nil)
@size = size
@board = GameBoard.new size, initial_life
@board.display name, 0
reason = generations.times do |gen|
new_board = evolve
new_board.display name, gen+1
break :all_dead if new_board.barren?
break :static if @board == new_board
@board = new_board
end
case reason
when :all_dead then puts "No more life."
when :static then puts "No movement."
else puts "Specified lifetime ended."
end
puts
end
def evolve
life = @board.each_index.select {|i,j| cell_fate(i,j)}
GameBoard.new @size, life
end
def cell_fate(i, j)
left_right = [0, i-1].max .. [i+1, @size-1].min
top_bottom = [0, j-1].max .. [j+1, @size-1].min
sum = 0
for x in left_right
for y in top_bottom
sum += @board[x,y].value if x != i or y != j
end
end
sum == 3 or (sum == 2 and @board[i,j].alive?)
end
end
class GameBoard
include Enumerable
def initialize(size, initial_life=nil)
@size = size
@board = Array.new(size) {Array.new(size) {Cell.new false}}
seed_board initial_life
end
def seed_board(life)
if life.nil?
# randomly seed board
each_index.to_a.sample(10).each {|x,y| @board[y][x].live}
else
life.each {|x,y| @board[y][x].live}
end
end
def each
@size.times {|x| @size.times {|y| yield @board[y][x] }}
end
def each_index
return to_enum(__method__) unless block_given?
@size.times {|x| @size.times {|y| yield x,y }}
end
def [](x, y)
@board[y][x]
end
def ==(board)
self.life == board.life
end
def barren?
none? {|cell| cell.alive?}
end
def life
each_index.select {|x,y| @board[y][x].alive?}
end
def display(name, generation)
puts "#{name}: generation #{generation}"
puts @board.map {|row| row.map {|cell| cell.alive? ? '#' : '.'}.join(' ')}
end
def apocalypse
# utility function to entirely clear the game board
each {|cell| cell.die}
end
end
class Cell
def initialize(alive) @alive = alive end
def alive?; @alive end
def value; @alive ? 1 : 0 end
def live; @alive = true end
def die; @alive = false end
end
Game.new "blinker", 3, 2, [[1,0],[1,1],[1,2]]
Game.new "glider", 4, 4, [[1,0],[2,1],[0,2],[1,2],[2,2]]
Game.new "random", 5, 10
You may also check:How to resolve the algorithm Balanced brackets step by step in the Seed7 programming language
You may also check:How to resolve the algorithm CUSIP step by step in the Factor programming language
You may also check:How to resolve the algorithm Perfect numbers step by step in the COBOL programming language
You may also check:How to resolve the algorithm Hamming numbers step by step in the jq programming language
You may also check:How to resolve the algorithm Pangram checker step by step in the Arturo programming language