Skip to content

Instantly share code, notes, and snippets.

Created September 1, 2015 15:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anonymous/894097cbb3ab324896ca to your computer and use it in GitHub Desktop.
Save anonymous/894097cbb3ab324896ca to your computer and use it in GitHub Desktop.
ALIVE = "*"
DEAD = " "
INTERVAL = 0.05
HEIGHT, WIDTH = `stty size`.split.map &:to_i
Signal.trap(:INT){ puts; exit 0 }
class Lifegame
def initialize(height = HEIGHT, width = WIDTH, alive = ALIVE, dead = DEAD)
set_size height, width
@alive = alive
@dead = dead
@turn = 0
end
def set_size(height, width)
@height = height
@width = width
reset
end
def reset
@field = Array.new(@height){ Array.new(@width){ rand(2) == 1 } }
end
def draw
@field.map{|row| row.map{|cell| cell ? @alive : @dead }.join } * "\n"
end
def get_cell(row, col)
@field[row][col]
end
def get_neighbors(row, col)
(-1..1).map do |i|
r = row + i
r -= @height if r >= @height
(-1..1).map do |j|
c = col + j
c -= @width if c >= @width
@field[r][c]
end
end
end
def count_neighbors(cell, row, col)
neighbors = get_neighbors row, col
neighbors.flatten.count(true) + (cell ? -1 : 0)
end
def next_status(row, col)
cell = get_cell row, col
neighbors = count_neighbors cell, row, col
judge cell, neighbors
end
def judge(cell, neighbors)
# セルが生存している時 => 周囲の生存セルが2つ or 3つだったら生存し続ける
# セルが死んでいる時 => 周囲の生存セルがちょうど3つだったら生まれる
# それ以外なら死ぬ
cell ? neighbors.between?(2, 3) : neighbors == 3
end
def advance #ターンを進める
@turn += 1
@field = Array.new(@height){|row| Array.new(@width){|col| next_status row, col } }
end
def active_cells
@field.flatten.count true
end
def run(interval = INTERVAL)
puts "\e[2J" #画面消去
loop do
start = Time.now.to_f #更新開始
print "\e[1;1H" #1行目の1列目にカーソル移動
print draw #フィールドを出力
print "\e[#{@height};1H" #一番下の行にカーソル移動
print "%5d turn, %5d cells alive. " % [@turn, active_cells] #ステータス行を出力
print "\e[#{@height};#{@width}H" #右下にカーソル移動 (やったほうが美しい)
advance #状態を更新
stop = Time.now.to_f #更新終了
elapsed = stop - start #作業にかかった時間
#スリープ (画面が大きいと割とモッサリするから作業時間はインターバルからマイナスする)
sleep interval < elapsed ? 0 : interval - elapsed
end
end
end
Lifegame.new.run
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment