本文实现了一个随机小世界的繁衍过程,可以控制迭代速度,纯原生js实现
<div style="display:inline-block;">第<span id="generation" style="width: 100px;"></span>代<button onclick="reset();">重置</button><button onclick="start();">开始</button><input id="speed" placeholder="100 ms/g" style="width: 80px"><button onclick="stop();">暂停</button><button onclick="nextGeneration();">下一代</button></div><hr><div><canvas id="myCanvas" width="400" height="400">您的浏览器不支持HTML5</canvas></div> <script> var canvas = document.getElementById("myCanvas"); var height = canvas.height, width = canvas.width, context = canvas.getContext("2d"); var lastData = []; // 记录上一代的数据 var data = []; // (height+2) * (width + 2) var imageData; var generation; var born = 3, // 当周围有三个活着的时候,这个位置会活一个 keep = 2; // 当周围有两个的时候,这个位置不变,其他情况都死 var running; // 是否运行 var intervalTime = 100; // 每次迭代的时间间隔
// 初始化数据和canvas
function init() {
generation = 0;
running = false;
intervalTime = parseInt(document.getElementById("speed").value);
lastData = buildTwoDArray(height + 2, width + 2);
data = buildTwoDArray(height + 2, width + 2);
context.clearRect(0, 0, width, height);
imageData = context.getImageData(0, 0, width, height);
document.getElementById("generation").innerHTML = generation.toString();
random();
}
// 随机生成数据
function random() {
// 生成画面的内容,即data的数据
for (var i = 0; i < height; i++) {
for (var j = 0; j < width; j++) {
if (Math.random() > 0.8) {
data[i + 1][j + 1] = 1;
}
}
}
// 随机生成后要画出来
paint();
}
// 将数据花到canvas上
function paint() {
var d = imageData.data;
// 生成绘制到canvas上的,下面代码的操作对象是图像流(数组)
for (var i = 0; i < height; i++) {
for (var j = 0; j < width; j++) {
if (data[i + 1][j + 1] && !lastData[i + 1][j + 1]) {
var pos = (i * width + j) * 4;
// 有生命,变成红色
d[pos] = 255; // red
d[pos + 1] = 0; // green
d[pos + 2] = 0; // blue
d[pos + 3] = 255; // 阿尔法通道,这个不设置会变成全透明
} else if (!data[i + 1][j + 1] && lastData[i + 1][j + 1]) {
var pos = (i * width + j) * 4;
// 有生命,变成红色
d[pos] = 255; // red
d[pos + 1] = 255; // green
d[pos + 2] = 255; // blue
}
}
}
context.putImageData(imageData, 0, 0);
document.getElementById("generation").innerHTML = generation.toString();
}
// 生成二维数组,所有初始化为0
function buildTwoDArray(x, y) {
var arr = [];
for (var i = 0; i < x; i++) {
arr[i] = [];
for (var j = 0; j < y; j++) {
arr[i][j] = 0;
}
}
return arr;
}
// 进行这一代的计算,并将上一代的数据保存到lastData中
function generate() {
lastData = data;
data = buildTwoDArray(height + 2, width + 2);
// 重新生成新一代的数据
for (var i = 1; i <= height; i++) {
for (var j = 1; j <= width; j++) {
// 周围有几个或者的
var state = lastData[i - 1][j - 1] + lastData[i - 1][j] + lastData[i - 1][j + 1] +
lastData[i][j - 1] + lastData[i][j + 1] +
lastData[i + 1][j - 1] + lastData[i + 1][j] + lastData[i + 1][j + 1];
if (state == born) {
data[i][j] = 1;
} else if (state == keep) {
data[i][j] = lastData[i][j];
} else {
data[i][j] = 0;
}
}
}
generation++;
}
function start() {
intervalTime = parseInt(document.getElementById("speed").value);
function run() {
if (running) {
setTimeout(function () {
paint();
generate();
run();
}, intervalTime);
}
}
running = true;
run();
}
function stop() {
running = false;
}
function reset() {
init();
}
function nextGeneration() {
paint();
generate();
}
window.addEventListener("load", init, true);
</script>