我正在尝试用JavaScript制作Conway的《人生游戏》,但是经过数小时的调试,却找不到特定功能的问题。
该程序通过创建一个基于全局“行”和“列”变量的2D数组来工作,然后将“ Square”对象推入数组中的每个空间。然后,程序将“绘制”功能的间隔设置为特定间隔(全局变量“比率”)。
如果这很难理解,我深表歉意,但是基本上,每个特定的时间间隔(例如每1000毫秒),程序都会检查数组中的每个“ Square”对象,更新其拥有的邻居数量,然后在其上进行绘制屏幕。
这就是我被困住的地方;更新功能应该检查一个正方形具有的所有8个邻居(如果是边缘正方形则检查3-5个),但它只会检查4个邻居。无论我做什么,如果我单击一个正方形来填充它,则只有现在填充的正方形的顶部,左上角,右上角和左邻居会记录其邻居已被填充。
除了此bug之外,代码还可以正常工作,我99%确信问题出在这一功能上,因为该代码目前仍将充当自动机,而不是作为Conway的《生命游戏》。
var canvas = document.getElementById("life");
var ctx = canvas.getContext('2d');
var timer;
var rate = 1000;
var rows = 20;
var columns = 20;
var width = 20;
var clickX;
var clickY;
var board;
var running = false;
var checkArray = [
[-1, 0, 1, 1, 1, 0, -1, -1],
[-1, -1, -1, 0, 1, 1, 1, 0]
];
var visuals = true;
var gridColor = "#000000";
/*
live cell with < 2 neighbors = death
live cell with 2 or 3 neighbors = live for 1 generation
live cell with > 4 neighbors = death
dead cell with 3 neighbors = live for 1 generation
0 = death
1 = death
2 = continues life if alive
3 = continues life if alive OR brings to life if dead
4 = death
5 = death
6 = death
7 = death
8 = death
*/
window.onload = function() {
makeBoard();
var timer = setInterval(draw, rate);
window.addEventListener("mousedown", clickHandler);
// for(var i = 0; i < 8; i++){
// var checkIndexX = checkArray[0][i];
// var checkIndexY = checkArray[1][i];
// console.log(checkIndexX, checkIndexY);
// }
}
function makeBoard() {
board = new Array(columns);
for (var i = 0; i < rows; i++) {
var intRow = new Array(rows);
for (var j = 0; j < columns; j++) {
intRow[j] = new Square(false, j, i);
}
board[i] = intRow;
}
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (var y = 0; y < rows; y++) {
for (var x = 0; x < columns; x++) {
if (running) {
board[y][x].update();
}
board[y][x].draw();
if (visuals) {
board[y][x].visuals();
}
}
}
drawRunButton();
}
function Square(alive, PARX, PARY) {
this.alive = false;
this.X = PARX;
this.Y = PARY;
this.neighbors = 0;
this.update = function() {
this.neighbors = 0;
for (var i = 0; i < 8; i++) {
var checkIndexX = checkArray[0][i];
var checkIndexY = checkArray[1][i];
if ((this.X + checkIndexX) >= 0 && (this.X + checkIndexX) < columns &&
(this.Y + checkIndexY) >= 0 && (this.Y + checkIndexY) < rows) {
var check = board[this.Y + checkIndexY][this.X + checkIndexX];
// console.log(this.X, this.Y, check.X, check.Y, checkIndexX, checkIndexY);
if (check.alive) {
this.neighbors++;
}
}
}
if (this.alive) {
if (this.neighbors < 2 || this.neighbors > 3) {
this.alive = false;
}
} else {
if (this.neighbors == 3) {
this.alive = true;
}
}
};
this.visuals = function() {
drawVisuals(this.neighbors, this.X * width, this.Y * width);
};
this.draw = function(alive) {
drawSquare(this.alive, this.X * width, this.Y * width, width);
}
}
function clickHandler(e) {
var clickX = e.screenX - 68;
var clickY = e.screenY - 112;
mapClick(clickX, clickY);
manageRun(clickX, clickY);
}
function mapClick(x, y) {
var indexX = Math.floor(x / width);
var indexY = Math.floor(y / width);
if (indexX >= 0 && indexX < columns && indexY >= 0 && indexY < rows) {
board[indexY][indexX].alive = true;
}
}
function manageRun(x, y) {
if (x >= (columns * width) + 5 && x <= (columns * width) + 45 && y >= 5 && y <= 45) {
if (running) {
running = false;
} else {
running = true;
}
console.log(running);
}
}
function drawRunButton() {
drawSquare(false, (columns * width) + 5, 5, 40)
}
function drawSquare(fill, x, y, width) {
ctx.beginPath();
ctx.moveTo(x, y);
ctx.lineTo(x + width, y);
ctx.lineTo(x + width, y + width);
ctx.lineTo(x, y + width);
ctx.lineTo(x, y);
if (fill) {
ctx.fillStyle = gridColor;
ctx.fill();
} else {
ctx.strokeStyle = gridColor;
ctx.stroke();
}
}
function drawVisuals(neighbors, x, y) {
ctx.beginPath();
ctx.fillStyle = "#ff0000";
ctx.font = '20px serif';
ctx.fillText(neighbors, x + (width / 3), y + (width / 1.25));
}
<!DOCTYPE html>
<html>
<head>
<title>template.com</title>
<link href="style.css" type="text/css" rel="stylesheet">
</head>
<body>
<canvas id="life" width="1400" height="700" style="border: 1px solid black"></canvas>
</body>
</html>