Skip to content

Instantly share code, notes, and snippets.

@obelisk68
Created February 19, 2018 13:40
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 obelisk68/153d7a7d283c8e8838dfe08a2511563e to your computer and use it in GitHub Desktop.
Save obelisk68/153d7a7d283c8e8838dfe08a2511563e to your computer and use it in GitHub Desktop.
Ruby でライフゲーム(with GTK+)
require 'gtk2'
Width = 30
Height = 30
class Component
def initialize
f = Field.new(Width, Height)
f.generate(150)
if ARGV[0] == "-r"
File.open("lifemap.txt") {|io| f = Marshal.load(io)}
else
File.open("lifemap.txt", "w") {|io| Marshal.dump(f, io)}
end
@window = Gui.new(f)
@disp = FieldDisplay.new(f)
end
def main
@disp.show
end
end
class Field
def initialize(width, height)
@width = width
@height = height
@field = Array.new(@width + 2) {Array.new(@height + 2, 0)}
end
attr_reader :width, :height
def set(x, y)
@field[x][y] = 1
end
def reset(x, y)
@field[x][y] = 0
end
def get(x, y)
if false #trueだと上下端、左右端がつながる
x = @width if x == 0
x = 1 if x == @width + 1
y = @height if y == 0
y = 1 if y == @height + 1
end
@field[x][y]
end
def generate(n)
n.times {set(rand(@width) + 1, rand(@height) + 1)}
end
def next
nxf = Array.new(@width + 2) {Array.new(@height + 2, 0)}
@width.times do |x|
@height.times do |y|
x1, y1 = x + 1, y + 1
n = alive_cells(x1, y1)
if get(x1, y1).zero?
nxf[x1][y1] = 1 if n == 3
else
nxf[x1][y1] = 1 if n == 2 or n == 3
end
end
end
@field = nxf
end
def alive_cells(x, y)
get(x - 1, y - 1) + get(x, y - 1) + get(x + 1, y - 1) +
get(x - 1, y) + get(x + 1, y) +
get(x - 1, y + 1) + get(x, y + 1) + get(x + 1, y + 1)
end
end
class Gui
CellWidth = 10
Space = 3
Margin = 8
def initialize(f)
@f = f
@w = Gtk::Window.new
@width = CellWidth * @f.width + Space * (@f.width - 1) + 2 * Margin
@height = CellWidth * @f.height + Space * (@f.height - 1) + 2 * Margin
@w.set_size_request(@width, @height)
@w.set_app_paintable(true)
@w.realize
@drawable = @w.window
@gc = Gdk::GC.new(@drawable)
colormap = Gdk::Colormap.system
@white = Gdk::Color.new(65535, 65535, 65535)
@black = Gdk::Color.new(0, 0, 0)
colormap.alloc_color(@white, false, true)
colormap.alloc_color(@black, false, true)
end
end
class FieldDisplay < Gui
def initialize(f)
super(f)
end
def show
@w.signal_connect("expose_event") do
@gc.set_foreground(@black)
@drawable.draw_rectangle(@gc, true, 0, 0, @width, @height)
end
Gtk.timeout_add(160) do
@f.width.times do |x|
@f.height.times do |y|
if @f.get(x + 1, y + 1).zero?
reset(x + 1, y + 1)
else
set(x + 1, y + 1)
end
end
end
@f.next
end
@w.signal_connect("destroy") {Gtk.main_quit}
@w.show
Gtk.main
end
def set(x, y)
@gc.set_foreground(@white)
draw_cell(x, y)
end
def reset(x, y)
@gc.set_foreground(@black)
draw_cell(x, y)
end
def draw_cell(x, y)
x1 = Margin + (x - 1) * CellWidth + (x - 1) * Space
y1 = Margin + (y - 1) * CellWidth + (y - 1) * Space
@drawable.draw_rectangle(@gc, true, x1, y1, CellWidth, CellWidth)
end
end
Component.new.main
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment