Zielony Smok

HTML5 canvas – tutorial

Mrówka Langtona

Automaty komórkowe zostały szerzej omówione i oprogramowane w książkach: “Matematyka dla programistów Java” oraz “Matematyka dla programistów JavaScript”. Linki do książek są po prawej stronie okna.

Użyty został skrypt ant.js.

Uzbrój się w cierpliwość. Niestety przeglądarki nie respektują czasów ustawianych w programach. Czasami czas faktyczny jest 20-krotnie dłuższy niż ustawiony.

Zawartość możesz zobaczyć w
przeglądarce obsługującej element <canvas>
z kontekstem "2d"


Listing

var ant = new Ant();
timer = setInterval("ant.run()", 10);
            

Skrypt ant.js

var cv = document.getElementById('canvas');
var ctx = cv.getContext('2d');
var width = cv.width;
var height = cv.height;
var w = 800;
var h = 800;
var liczbaPol = 100;
var ap = liczbaPol / 2;
var szer = 8;
var s = szer / 2;
var len = szer * liczbaPol;
var CW = "white";
var CB = "black";
var CR = "red";
var antx = ap;
var anty = ap;
var antDir = 1;
var timer;
var Ant = function() {
	this.autos1 = [];
	this.autos2 = [];
	for (var i = 0; i < liczbaPol; i++) {
		this.autos1[i] = [];
		this.autos2[i] = [];
	}
	this.clear();
};
Ant.prototype.clear = function() {
	for (var j = 0; j < liczbaPol; j++) {
		for (var k = 0; k < liczbaPol; k++) {
			this.autos1[j][k] = 0;
			this.autos2[j][k] = 0;
		}
	}
};
Ant.prototype.putStructure = function(x, y, array) {
	this.clear();
	for (var i = 0; i < array.length; i++) {
		for (var j = 0; j < array[0].length; j++) {
			this.autos1[i + y][j + x] = array[i][j];
		}
	}
};
Ant.prototype.run = function() {
	this.autos2 = clone(this.autos1);
	antDir = changeDir(antDir, this.autos2[antx][anty]);
	if (this.autos2[antx][anty] == 0) {
		this.autos2[antx][anty]++;
	} else if (this.autos2[antx][anty] == 1) {
		this.autos2[antx][anty]--;
	}
	if (antDir == 1) {
		anty--;
		if (anty == -1) {
			anty = liczbaPol - 1;
		}
	} else if (antDir == 2) {
		antx--;
		if (antx == -1) {
			antx = liczbaPol - 1;
		}
	} else if (antDir == 3) {
		anty++;
		if (anty == liczbaPol) {
			anty = 0;
		}
	} else if (antDir == 4) {
		antx++;
		if (antx == liczbaPol) {
			antx = 0;
		}
	}
	this.autos1 = clone(this.autos2);
	this.drawAnt();
};
Ant.prototype.drawAnt = function() {
	ctx.save();
	ctx.beginPath();
	ctx.fillStyle = CW;
	ctx.rect(0, 0, w, h);
	ctx.fill();
	ctx.strokeStyle = "lightgrey";
	var z = 0;// polozenie linii
	for (var i = 0; i <= liczbaPol + 1; i++) {
		ctx.moveTo(0, z);
		ctx.lineTo(len, z);
		ctx.moveTo(z, 0);
		ctx.lineTo(z, len);
		z += szer;
	}
	ctx.lineWidth = 0.5;
	ctx.stroke();
	ctx.beginPath();
	ctx.fillStyle = CB;
	for (var i = 0; i < liczbaPol; i++) {
		for (var j = 0; j < liczbaPol; j++) {
			var x = i * szer;
			var y = j * szer;
			if (this.autos1[i][j] == 1) {
				ctx.beginPath();
				ctx.rect(x, y, szer, szer);
				ctx.fill();
			}
			ctx.fillStyle = CR;
			ctx.beginPath();
			ctx.arc(antx * szer + s, anty * szer + s, s, 
                         0, 2 * Math.PI, false);
			ctx.fill();
			ctx.fillStyle = CB;
		}
	}
	ctx.restore();
}
function changeDir(dir, col) {
	var newDir = 0;
	switch (dir) {
	case 1:
		if (col == 0) {
			newDir = 2;
		} else if (col == 1) {
			newDir = 4;
		}
		break;
	case 2:
		if (col == 0) {
			newDir = 3;
		} else if (col == 1) {
			newDir = 1;
		}
		break;
	case 3:
		if (col == 0) {
			newDir = 4;
		} else if (col == 1) {
			newDir = 2;
		}
		break;
	case 4:
		if (col == 0) {
			newDir = 1;
		} else if (col == 1) {
			newDir = 3;
		}
		break;
	}
	return newDir;
};
function clone(array) {
	var r = array.length;
	var c = array[0].length;
	var array1 = [];
	for (var k = 0; k < r; k++) {
		array1[k] = [];
	}
	for (var i = 0; i < r; i++) {
		for (var j = 0; j < c; j++) {
			array1[i][j] = array[i][j];
		}
	}
	return array1;
};