Last active
April 3, 2017 17:42
-
-
Save woxtu/610b88dd09a3856bcb77899314e16039 to your computer and use it in GitHub Desktop.
Conway's Game of Life in Facebook/Reason
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"name": "lifegame", | |
"sources": [ | |
"./" | |
] | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<meta charset="utf-8"> | |
<title>Conway's Game of Life</title> | |
<body> | |
<canvas id="canvas" width="500" height="500"></canvas> | |
<script src="dist/main.js"></script> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Element = { | |
type t; | |
}; | |
module Context = { | |
type t; | |
external setFillStyle : t => string => unit = "fillStyle" [@@bs.set]; | |
external fillRect : int => int => int => int => unit = "" [@@bs.send.pipe: t]; | |
}; | |
module Canvas = { | |
type t = Element.t; | |
external width : t => int = "" [@@bs.get]; | |
external height : t => int = "" [@@bs.get]; | |
external getContext : string => Context.t = "" [@@bs.send.pipe: t]; | |
}; | |
module Document = { | |
external getElementById : string => option Element.t = "document.getElementById" [@@bs.val] [@@bs.return null_to_opt]; | |
}; | |
module Window = { | |
external requestAnimationFrame : (unit => unit) => unit = "" [@@bs.val]; | |
}; | |
module Array = { | |
include Array; | |
let filter = Js.Array.filter; | |
}; | |
type cell = Dead | Alive; | |
let size = 2; | |
let foregroundColor = "#F36"; | |
let backgroundColor = "#000"; | |
let clear canvas context => { | |
Context.setFillStyle context backgroundColor; | |
context |> Context.fillRect 0 0 (canvas |> Canvas.width) (canvas |> Canvas.height); | |
}; | |
let draw grid context => { | |
Context.setFillStyle context foregroundColor; | |
grid |> Array.iteri @@ fun x cells => | |
cells |> Array.iteri @@ fun y cell => switch cell { | |
| Alive => context |> Context.fillRect (x * size) (y * size) size size | |
| _ => () | |
} | |
}; | |
let rows grid => Array.length grid; | |
let columns grid => switch (Array.length grid) { | |
| length when 0 < length => Array.length @@ Array.get grid 0 | |
| _ => -1 | |
}; | |
let index min max n => switch n { | |
| n when n < min => max | |
| n when max < n => min | |
| n => n | |
}; | |
let neighbours x y grid => | |
[|(-1, -1), (-1, 0), (-1, 1), (0, -1), (0, 1), (1, -1), (1, 0), (1, 1)|] | |
|> Array.map @@ fun (a, b) => { | |
let m = index 0 (rows grid - 1) (x + a); | |
let n = index 0 (columns grid - 1) (y + b); | |
Array.get (Array.get grid m) n | |
}; | |
let next grid => | |
grid |> Array.mapi @@ fun x cells => | |
cells |> Array.mapi @@ fun y cell => | |
switch (neighbours x y grid |> Array.filter ((==) Alive) |> Array.length) { | |
| 3 => Alive | |
| 2 => cell | |
| _ => Dead | |
}; | |
let rec run canvas grid => { | |
let context = canvas |> Canvas.getContext "2d"; | |
context |> clear canvas; | |
context |> draw grid; | |
Window.requestAnimationFrame @@ fun () => run canvas @@ next grid | |
}; | |
let () = { | |
let canvas = switch (Document.getElementById "canvas") { | |
| None => failwith "Cannot find the canvas" | |
| Some canvas => canvas | |
}; | |
let rows = (canvas |> Canvas.width) / size; | |
let columns = (canvas |> Canvas.height) / size; | |
Random.self_init (); | |
let grid = | |
Array.make_matrix rows columns () |> Array.map @@ fun cells => | |
cells |> Array.map @@ fun _ => if (Random.bool ()) { Alive } else { Dead }; | |
run canvas grid | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"name": "lifegame", | |
"version": "0.1.0", | |
"private": true, | |
"license": "MIT", | |
"scripts": { | |
"build": "webpack", | |
"watch": "webpack -w", | |
"serve": "http-server", | |
"develop": "npm-run-all -p watch serve" | |
}, | |
"devDependencies": { | |
"bs-loader": "^1.1.0", | |
"bs-platform": "^1.5.2", | |
"http-server": "^0.9.0", | |
"npm-run-all": "^4.0.2", | |
"webpack": "^2.2.1" | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const path = require('path'); | |
module.exports = { | |
entry: { | |
main: './main.re', | |
}, | |
output: { | |
path: path.join(__dirname, 'dist'), | |
filename: '[name].js' | |
}, | |
module: { | |
rules: [ | |
{ test: /\.(re|ml)$/, use: 'bs-loader' }, | |
], | |
}, | |
resolve: { | |
extensions: ['.re', '.ml', '.js'], | |
}, | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment