ライフゲームの CoffeeScript 版

前回「コンウェイライフゲーム」を Ruby でシンプルに実装しましたが、今回その CoffeeScript 版です。ここで実行できるのがいいでしょう? 「実行」を押すとセルがランダムに生成されます。

セルの数:   

コード。HTML。

<form>
セルの数:<input type="text" name="num" size="4" value="170">
<input type="button" value="実行" onclick="start(this.form)">  
<input type="button" value="クリア" onclick="clear();">
</form>
<canvas id="Canvas" style="background-color: black;"></canvas>

CoffeeScript。 

width = 40; height = 40
cellwidth = 10; space = 3; margin = 8
wd = cellwidth * width  + space * (width  - 1) + 2 * margin
ht = cellwidth * height + space * (height - 1) + 2 * margin
ctx = f = w = id = null


Field = (width, height)->
  @width  = width
  @height = height
  @field = []
  for i in [0...(@width + 2)]
    @field[i] = []
    for j in [0...(@height + 2)]
      @field[i][j] = 0
  
  @generate = (n)->
    for i in [1..n]
      x = Math.floor(Math.random() * (@width  - 10)) + 5
      y = Math.floor(Math.random() * (@height - 10)) + 5
      @field[x][y] = 1
  
  @show = ->
    for x in [1..@width]
      for y in [1..@height]
        if @field[x][y]
          w.set(x, y)
        else
          w.reset(x, y)
  
  @windowx = (x)->
    margin + (x - 1) * cellwidth + (x - 1) * space
  
  @windowy = (y)->
    margin + (y - 1) * cellwidth + (y - 1) * space
  
  @next = ->
    nxf = []
    for i in [0...(@width + 2)]
      nxf[i] = []
      for j in [0...(@height + 2)]
        nxf[i][j] = 0
    for x in [1..@width]
      for y in [1..@height]
        n = @alive_cells(x, y)
        if @field[x][y]
          nxf[x][y] = 1 if n == 2 or n == 3
        else
          nxf[x][y] = 1 if n == 3
    @field = nxf
  
  @alive_cells = (x, y)->
    @field[x - 1][y - 1] + @field[x][y - 1] + @field[x + 1][y - 1] +
       @field[x - 1][y] + @field[x + 1][y] +
       @field[x - 1][y + 1] + @field[x][y + 1] + @field[x + 1][y + 1]
  
  null


Window = ->
  @set = (x, y)->
    ctx.fillStyle = "rgb(255, 255, 255)"
    @draw_cell(x, y)
  
  @reset = (x, y)->
    ctx.fillStyle = "rgb(0, 0, 0)"
    @draw_cell(x, y)
  
  @draw_cell = (x, y)->
    ctx.fillRect(f.windowx(x), f.windowy(y), cellwidth, cellwidth)
  
  null


mainloop = ->
  f.show()
  f.next()
  return


window.start = (e)->    #「実行」ボタンでここへ飛ぶ
  window.clearInterval(id) if id
  ctx.clearRect(0, 0, wd, ht)
  f = new Field(width, height)
  f.generate(parseInt(e.num.value))    #入力した数だけセルを生成する
  w = new Window()
  id = window.setInterval(mainloop, 200)
  return


window.clear = ->    #「クリア」ボタンでここへ飛ぶ
  window.clearInterval(id) if id
  ctx.clearRect(0, 0, wd, ht)
  return


$(window).load ->    #実際のコードは少しちがう
  cvs = document.getElementById("Canvas"); ctx = cvs.getContext("2d")
  cvs.width = wd; cvs.height = ht
  return

CoffeeScript では window.onload = が使えないので、jQuery$(window).load -> を使っている。