ライフゲーム

Rubyでライフゲームを作ってみた.

起動後,10×10みたいな感じでフィールドの大きさを入力.

あとはEnterを押すと世代が一つずつ進んでいく.

また,座標の指定をすれば,その座標の生死を切り替えられる.

以下にソースコードを示す.

lifegame.rb

#!/usr/bin/env ruby
require "lifegamefield.rb"
require "lifegameview.rb"
print "[幅x高さ]を入力してください: "
widthheight=gets.split(/x/)
width=widthheight[0].to_i
height=widthheight[1].to_i
lgf = LifeGame::Field.new(width,height)
view = LifeGame::ConsoleView.new(lgf)
g=0
loop do
print "=== generation #{g+1} ===\n"
view.visualize
cmd=""
loop do
print "状態を変更する場合はその座標をカンマ区切りで入力[x,y]:"
break if (cmd=gets) == "\n"
# 座標指定があれば
if cmd =~ /(\d+),(\d+)/
x=$1.to_i
y=$2.to_i
if lgf.isalive?(x,y)
lgf.kill(x,y)
else
lgf.create(x,y)
end
end
view.visualize
end
break if cmd=="exit"
lgf.update
g+=1
end

lifegamefield.rb

module LifeGame
class Field
attr_reader :width,:height
def initialize(width,height)
@width=width
@height=height
init
end
def init
@field=[]
@height.times do |h|
line=[]
@width.times do |w|
line.push(false)
end
@field.push(line)
end
end
def isalive?(x,y)
return false if x >= @width
return false if y >= @height
return @field[y][x]
end
def create(x,y)
return false if x >= @width
return false if y >= @height
@field[y][x]=true
end
def kill(x,y)
return false if x >= @width
return false if y >= @height
@field[y][x]=false
end
def update
# life game のメインルーチン
newfield=@field.map{|x| x.clone}
@height.times do |h|
@width.times do |w|
count=getlivecount(h,w)
if @field[h][w]
# 8近傍のうち生きているのが2つか3つでないなら死ぬ
newfield[h][w]=false if count != 2 and count != 3
else
# 8近傍のうち生きているのが3つだったら生きる
newfield[h][w]=true if count == 3
end
end
end
@field=newfield
end
def getlivecount(h,w)
count=0
(-1..1).each do |dy|
(-1..1).each do |dx|
next if dy==0 and dx==0
count += 1 if @field[h-dy] != nil and @field[h-dy][w-dx]
end
end
return count
end
end
end

lifegameview.rb

module LifeGame
class ConsoleView
def initialize(field)
@field=field
end
def visualize
@field.height.times do |h|
@field.width.times do |w|
state=@field.isalive?(w,h)
print "" if state
print "" unless state
end
print "\n"
end
end
end
end

ついでにWebアプリにもしてみたいけど,めんどくさいので今日はここまで.

コメントする