メモ帳でできるプログラミング JavaScript

ライフゲーム

説明なし。

デモ

世代

プログラム

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>ライフゲーム</title>
<style>
</style>
<script>
window.onload = function() {
	var c = 10;
	var w = 50;
	var h = 50;
	var t = 100;
	var tid;
	var g = 1;
	var d = [];
	for (var y = 0; y < h; ++y) {
		d[y] = [];
		for (var x = 0; x < w; ++x) {
			d[y][x] = 0;
		}
	}
	var canvas = document.getElementById('c');
	var ctx = canvas.getContext("2d");
	canvas.width = c * w;
	canvas.height = c * h;

	function draw(d, c, w, h, g, b) {
		for (var y = 0; y < h; ++y) {
			for (var x = 0; x < w; ++x) {
				if (!(b && b[y] && (b[y][x] == d[y][x]))) {
					ctx.fillStyle = (d[y][x]) ? '#003366' : '#eeeeff';
					ctx.beginPath();
					ctx.rect(x * c, y * c, c, c);
					ctx.closePath();
					ctx.fill();
				}
			}
		}
		document.f.g.value = g;
	}

	function calc(d, w, h) {
		var e = [];
		for (var y = 0; y < h; ++y) {
			e[y] = [];
			for (var x = 0; x < w; ++x) {
				//生存、誕生以外は過疎、過密で死滅
				e[y][x] = 0;
				//周囲の個体数(上辺のさらに上は下辺、左辺のさらに左は右辺…のようにしている)
				var k = d[(h + y - 1) % h][(w + x - 1) % w]
					+ d[(h + y - 1) % h][(w + x + 0) % w]
					+ d[(h + y - 1) % h][(w + x + 1) % w]
					+ d[(h + y + 0) % h][(w + x - 1) % w]
					+ d[(h + y + 0) % h][(w + x + 1) % w]
					+ d[(h + y + 1) % h][(w + x - 1) % w]
					+ d[(h + y + 1) % h][(w + x + 0) % w]
					+ d[(h + y + 1) % h][(w + x + 1) % w];

				if (d[y][x]) {
					if ((k == 2) || (k == 3)) {
						//生存
						e[y][x] = 1;
					}
				} else {
					if (k == 3) {
						//誕生
						e[y][x] = 1;
					}
				}
			}
		}
		return e;
	}

	function tsugi() {
		var b = d;
		d = calc(b, w, h);
		++g;
		draw(d, c, w, h, g, b);
	}

	function susumu() {
		if (!tid) {
			tid = setInterval(tsugi, t);
		}
	}

	function tomeru() {
		clearInterval(tid);
		tid = 0;
	}

	function komaokuri() {
		tsugi();
	}

	function life(e) {
		var rect = e.target.getBoundingClientRect();
		var x = Math.floor((e.clientX - rect.left) / c);
		var y = Math.floor((e.clientY - rect.top) / c);
		d[y][x] = d[y][x] ? 0 : 1;
		draw(d, c, w, h, g);
	}

	function pattern(e) {
		var p = JSON.parse(e.target.dataset.d);
		d = [];
		for (var y = 0; y < h; ++y) {
			d[y] = [];
			for (var x = 0; x < w; ++x) {
				d[y][x] = (p && p[y] && p[y][x] ? 1 : 0);
			}
		}
		g = 1;
		draw(d, c, w, h, g);
	}

	document.f.b1.addEventListener('click', susumu);
	document.f.b2.addEventListener('click', tomeru);
	document.f.b3.addEventListener('click', komaokuri);
	document.getElementById('c').addEventListener('click', life);
	for (var i = 0; i < document.getElementById('d').children.length; ++i) {
		document.getElementById('d').children[i].addEventListener('click', pattern);
	}

	draw(d, c, w, h, g);
}
</script>
</head>
<body>
	<form name="f">
		<div id="a">
			<p>
				<button type="button" name="b1">進む</button>
				<button type="button" name="b2">止める</button>
				<button type="button" name="b3">一つ進む</button>
				<input type="text" name="g" size="5" readonly>世代
			</p>
		</div>
		<div id="b">
			<canvas id="c"></canvas>
		</div>
		<div id="d">
			<button type="button" data-d="[[]]">クリア</button>
			<button type="button" data-d="[[],[0,0,1,0],[0,0,0,1],[0,1,1,1]]">グライダー</button>
			<button type="button" data-d="[[],[0,1,0,0,1],[0,0,0,0,0,1],[0,1,0,0,0,1],[0,0,1,1,1,1]]">宇宙船(小)</button>
			<button type="button" data-d="[[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1]]">ペンタデカスロン</button>
			<button type="button" data-d="[[],[],[0,0,0,1,0,0],[0,0,0,0,1,1],[0,0,1,1,0,0],[0,0,0,0,1,0]]">時計</button>
			<button type="button" data-d="[[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[0,0,0,0,0,0,0,0,0,0,1,1,1,1,1]]">-</button>
		</div>
	</form>
</body>
</html>

解説

(追記予定)