Евгения обнови решението на 19.12.2011 03:30 (преди над 12 години)
+module GameOfLife
+
+ class Cell
+ def initialize(x, y, live = false)
+ @x = x
+ @y = y
+ @live = live
+ end
+
+ def coordinates
+ [@x, @y]
+ end
+
+ def live_area
+ # return the 9 squares containing the given cell in the middle
+ (@x - 1).upto(@x + 1).to_a.product (@y - 1).upto(@y + 1).to_a
+ end
+
+ def live?
+ @live # maybe the same as: alias :live? :live
+ end
+ end
+
+ class Board
+ include Enumerable
+
+ def initialize(*initial_cells)
+ @live_cells = []
+
+ initial_cells.each do |cell|
+ @live_cells << Cell.new(cell[0], cell[1], true)
+ end
+
+ # or just: @live_cells = initial_cells.map { |cell| Cell.new(cell[0], cell[1], true) }
+ end
+
+ def [](x, y)
+ @live_cells.find { |cell| [x, y] == cell.coordinates } != nil
+ end
+
+ def each
+ return @live_cells unless block_given?
+
+ @live_cells.each do |cell|
+ yield cell.coordinates
+ end
+ end
+
+ def next_generation
+ Generation.new(self).next # how to remove this dependency ?
+ end
+
+ def live_area
+ # returns all live cells on the board + treir surroundings
+ @live_cells.map { |cell| cell.live_area }.inject(:|) # merge returned sets
+ end
+ end
+
+ class Population
+
+ def initialize(cell, board)
+ @cell = cell
+ @board = board
+ end
+
+ def survive?
+ @cell.live? and count.between? 2, 3
+ end
+
+ def reproduct?
+ not @cell.live? and count == 3
+ end
+
+ private
+
+ def count
+ neighbours.find_all { |cell| cell.live? }.count
+ end
+
+ def neighbours
+ ( @cell.live_area - [@cell.coordinates] ).map do |x, y|
+ Cell.new(x, y, @board[x, y])
+ end
+ end
+
+ end
+
+ class Generation
+
+ def initialize(board)
+ @board = board
+ end
+
+ def next
+ Board.new *next_generation
+ end
+
+ private
+
+ def next_generation
+ @board.live_area.find_all do |x, y|
+ population = Population.new Cell.new(x, y, @board[x, y]), @board
+ population.survive? or population.reproduct?
+ end
+ end
+
+ end
+
+end
- В
#count
може да подадеш блока направо наEnumerable#count
и да си спестишfind_all
- Имаш нужда от малки корекции в спазването на конвенциите за whitespace/скоби. Виж този Ruby style guide. (Подкрепям 90% от нещата, казани там.)
- Класът
Cell
може би можеше да се спести :) Може би като цяло решението е леко over-engineered. Разгледай решенията на другите, има някои интересни.