Help us understand the problem. What is going on with this article?

二次元セルオートマトン(ライフゲーム)

More than 3 years have passed since last update.

一次元セルオートマトンの続き。
詳細はwikiへ。
二次元セルオートマトンの中でもこのルールのことをライフゲームと呼ぶようです。

Ruby

init

Array.newにブロックを渡すと良しなに初期化してくれます。

class Lifegame
  attr_accessor :cells

  def initialize(y = 0,x = 0)
    @cells = Array.new(y) { Array.new(x,0) }
  end

rule

前回と違いパターンないしルールは固定。
自分の生死と周囲の生きている数を元に明日の生死が決まります。
孤独だと死。騒がしくても死。丁度良いと生き返ったりします。

  def rule(*cs)
    case cs
    when [1, 2] then 1
    when [1, 3] then 1
    when [0, 3] then 1
    else 0
    end
  end

apply

配列の外を参照しない様に確認しながら、
周囲の生きている数を数え上げ、ルールに適応します。
前回教えていただいたproductが使えスッキリしてます。

  def apply
    sy = @cells.size
    sx = @cells[0].size
    as = [-1,0,1]

    @cells = @cells.map.with_index { |cy,iy|
      cy.map.with_index { |c,ix|
        rule(c,
          as.product(as).map { |ay,ax| 
            if ay == 0 && ax == 0
              0
            else
              y = iy + ay
              x = ix + ax
              if y >= 0 && y < sy && x >= 0 && x < sx
                @cells[y][x]
              else
                0
              end
            end
          }.reduce(:+)
        )
      }
    }
  end

random

セルを手で打つのはだるいのでランダムに任せます。
一応ブロックで調整できます。
コクのある乱数など試して見ましょう。

  def random
    @cells = @cells.map { |y|
      y.map { |x| 
        if block_given?
          yield x
        else
          rand(2) 
        end
      }
    }
  end

show, run

clearコマンドでターミナルの画面でアニメーション(遅い)
その場合はsleepで調整。

  def show
    @cells.map { |y| y.map { |x| x == 0 ? " " : "O" }.join + "\n" }.join + "\n"
  end

  def run n = 200,m = 0.1
    g = 0
    for nn in 1 .. n
      system "clear"
      puts "Gen: #{g}\n#{show}"
      g += 1
      apply
      sleep m
    end
  end
end

main

サイズが大きすぎると遅いので調整しましょう。
私のターミナルは縦25*横100しかないのでこれくらいで十分です。
めっちゃフォントを大きくしてます。

require "io/console"
y,x = IO.console.winsize
cs = Lifegame.new(y-3,x)
cs.random { (rand(2) + rand(2) + rand(2)) / 3 }
cs.run(50)

lifegame_terminal.gif

end

ttygif使って見たけどいまいちカクカク。
実際はもう少しなめらかです。

kmtoki
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away