用 Javascript 实现康威的生命游戏 - 细胞逻辑问题
我决定编写自己的 Conway 生命游戏实现,并选择了 Javascript。它是纯DHTML。我已经整理了基础知识,但它似乎不符合正常的生命游戏行为。例如,像滑翔机这样的模式不是“滑翔”,振荡器不是振荡。我花了很多时间尝试各种逻辑,并进行了十多次重写。
所以,如果我制作了滑翔机图案,一代后它就会变成方形静物画。
这是 Javascript 代码(很抱歉没有注释的代码):
var chanceOfLiveCells = 0.1;
var gridReference = null;
var gridDimension = 15;
var cells = null;
var cellsAlive = 0;
var cellsDead = 0;
var currentGeneration = 0;
function init() {
gridReference = document.getElementById('grid');
cells = new Array();
drawGrid();
placeRandomCells();
nextGeneration();
}
function drawGrid() {
var gridArray = new Array();
var counter = 0;
for(var x = 0; x <= gridDimension - 1; x = x + 1) {
gridArray.push('<tr>');
for(var y = 0; y <= gridDimension - 1; y = y + 1) {
//gridArray.push('<td id="' + counter + '">' + x + ', ' + y + ' (' + counter + ')' + '</td>');
gridArray.push('<td id="' + counter + '"></td>');
cells.push(counter);
counter = counter + 1;
}
gridArray.push('</tr>');
}
grid = gridArray.join('');
gridReference.innerHTML = grid;
}
function nextGeneration() {
currentGeneration = currentGeneration + 1;
for(var x = 0; x <= gridDimension - 1; x = x + 1) {
for(var y = 0; y <= gridDimension - 1; y = y + 1) {
var neighbours = cellNeighbourCount(x, y);
if(isCellLive(x, y) == true) {
if(neighbours < 2) {
setDeadCell(x, y);
cellsDead = cellsDead + 1;
}
if(neighbours == 2 || neighbours == 3) {
setLiveCell(x, y);
cellsAlive = cellsAlive + 1;
}
if(neighbours > 3) {
setDeadCell(x, y);
cellsDead = cellsDead + 1;
}
}
else if(isCellLive(x, y) == false){
if(neighbours == 3) {
setLiveCell(x, y);
cellsAlive = cellsAlive + 1;
}
}
}
}
document.getElementById('currentGeneration').innerHTML = currentGeneration;
document.getElementById('cellsAlive').innerHTML = cellsAlive;
document.getElementById('cellsDead').innerHTML = cellsDead;
cellsAlive = 0;
cellsDead = 0;
setTimeout('nextGeneration()', 200);
}
function placeRandomCells() {
for(var x = 0; x <= gridDimension - 1; x = x + 1) {
for(var y = 0; y <= gridDimension - 1; y = y + 1) {
if(Math.random() < chanceOfLiveCells) {
setLiveCell(x, y);
}
else {
setDeadCell(x, y);
}
}
}
}
function setLiveCell(x, y) {
document.getElementById(getCell(x, y)).style.backgroundColor = 'red';
}
function setDeadCell(x, y) {
document.getElementById(getCell(x, y)).style.backgroundColor = 'maroon';
}
function cellNeighbourCount(x, y) {
var count = 0;
if(isCellLive(x - 1, y) == true) {
count = count + 1;
}
if(isCellLive(x - 1, y + 1) == true) {
count = count + 1;
}
if(isCellLive(x, y + 1) == true) {
count = count + 1;
}
if(isCellLive(x + 1, y + 1) == true) {
count = count + 1;
}
if(isCellLive(x + 1, y) == true) {
count = count + 1;
}
if(isCellLive(x + 1, y - 1) == true) {
count = count + 1;
}
if(isCellLive(x, y - 1) == true) {
count = count + 1;
}
if(isCellLive(x - 1, y - 1) == true) {
count = count + 1;
}
return count;
}
function isCellLive(x, y) {
if(document.getElementById(getCell(x, y)).style.backgroundColor == 'red') {
return true;
}
return false;
}
function getCell(x, y) {
if(x >= gridDimension) {
x = 0;
}
if(y >= gridDimension) {
y = 0;
}
if(x < 0) {
x = gridDimension - 1;
}
if(y < 0) {
y = gridDimension - 1;
}
return cells[x * gridDimension + y];
}
function createSquare() {
setLiveCell(4, 4);
setLiveCell(4, 5);
setLiveCell(4, 6);
setLiveCell(5, 6);
setLiveCell(6, 6);
setLiveCell(6, 5);
setLiveCell(6, 4);
setLiveCell(5, 4);
}
function createBlinker() {
setLiveCell(4, 5);
setLiveCell(5, 5);
setLiveCell(6, 5);
}
function createBeacon() {
setLiveCell(4, 4);
setLiveCell(4, 5);
setLiveCell(5, 4);
setLiveCell(5, 5);
setLiveCell(6, 6);
setLiveCell(6, 7);
setLiveCell(7, 6);
setLiveCell(7, 7);
}
I decided to write my own implementation of Conway's Game of Life, and chose Javascript. It is pure DHTML. I have the basics sorted out, but it seems to not correspond to normal Game of Life behaviour. For example, patterns like gliders aren't 'gliding', oscillators aren't oscillating. I have spent a good amount of time trying various logic and have done over ten re-writes.
So, if I had made the glider pattern, it would just turn into a square still life after one generation.
Here is the Javascript code (sorry about the uncommented code):
var chanceOfLiveCells = 0.1;
var gridReference = null;
var gridDimension = 15;
var cells = null;
var cellsAlive = 0;
var cellsDead = 0;
var currentGeneration = 0;
function init() {
gridReference = document.getElementById('grid');
cells = new Array();
drawGrid();
placeRandomCells();
nextGeneration();
}
function drawGrid() {
var gridArray = new Array();
var counter = 0;
for(var x = 0; x <= gridDimension - 1; x = x + 1) {
gridArray.push('<tr>');
for(var y = 0; y <= gridDimension - 1; y = y + 1) {
//gridArray.push('<td id="' + counter + '">' + x + ', ' + y + ' (' + counter + ')' + '</td>');
gridArray.push('<td id="' + counter + '"></td>');
cells.push(counter);
counter = counter + 1;
}
gridArray.push('</tr>');
}
grid = gridArray.join('');
gridReference.innerHTML = grid;
}
function nextGeneration() {
currentGeneration = currentGeneration + 1;
for(var x = 0; x <= gridDimension - 1; x = x + 1) {
for(var y = 0; y <= gridDimension - 1; y = y + 1) {
var neighbours = cellNeighbourCount(x, y);
if(isCellLive(x, y) == true) {
if(neighbours < 2) {
setDeadCell(x, y);
cellsDead = cellsDead + 1;
}
if(neighbours == 2 || neighbours == 3) {
setLiveCell(x, y);
cellsAlive = cellsAlive + 1;
}
if(neighbours > 3) {
setDeadCell(x, y);
cellsDead = cellsDead + 1;
}
}
else if(isCellLive(x, y) == false){
if(neighbours == 3) {
setLiveCell(x, y);
cellsAlive = cellsAlive + 1;
}
}
}
}
document.getElementById('currentGeneration').innerHTML = currentGeneration;
document.getElementById('cellsAlive').innerHTML = cellsAlive;
document.getElementById('cellsDead').innerHTML = cellsDead;
cellsAlive = 0;
cellsDead = 0;
setTimeout('nextGeneration()', 200);
}
function placeRandomCells() {
for(var x = 0; x <= gridDimension - 1; x = x + 1) {
for(var y = 0; y <= gridDimension - 1; y = y + 1) {
if(Math.random() < chanceOfLiveCells) {
setLiveCell(x, y);
}
else {
setDeadCell(x, y);
}
}
}
}
function setLiveCell(x, y) {
document.getElementById(getCell(x, y)).style.backgroundColor = 'red';
}
function setDeadCell(x, y) {
document.getElementById(getCell(x, y)).style.backgroundColor = 'maroon';
}
function cellNeighbourCount(x, y) {
var count = 0;
if(isCellLive(x - 1, y) == true) {
count = count + 1;
}
if(isCellLive(x - 1, y + 1) == true) {
count = count + 1;
}
if(isCellLive(x, y + 1) == true) {
count = count + 1;
}
if(isCellLive(x + 1, y + 1) == true) {
count = count + 1;
}
if(isCellLive(x + 1, y) == true) {
count = count + 1;
}
if(isCellLive(x + 1, y - 1) == true) {
count = count + 1;
}
if(isCellLive(x, y - 1) == true) {
count = count + 1;
}
if(isCellLive(x - 1, y - 1) == true) {
count = count + 1;
}
return count;
}
function isCellLive(x, y) {
if(document.getElementById(getCell(x, y)).style.backgroundColor == 'red') {
return true;
}
return false;
}
function getCell(x, y) {
if(x >= gridDimension) {
x = 0;
}
if(y >= gridDimension) {
y = 0;
}
if(x < 0) {
x = gridDimension - 1;
}
if(y < 0) {
y = gridDimension - 1;
}
return cells[x * gridDimension + y];
}
function createSquare() {
setLiveCell(4, 4);
setLiveCell(4, 5);
setLiveCell(4, 6);
setLiveCell(5, 6);
setLiveCell(6, 6);
setLiveCell(6, 5);
setLiveCell(6, 4);
setLiveCell(5, 4);
}
function createBlinker() {
setLiveCell(4, 5);
setLiveCell(5, 5);
setLiveCell(6, 5);
}
function createBeacon() {
setLiveCell(4, 4);
setLiveCell(4, 5);
setLiveCell(5, 4);
setLiveCell(5, 5);
setLiveCell(6, 6);
setLiveCell(6, 7);
setLiveCell(7, 6);
setLiveCell(7, 7);
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
没有函数 'renderNextGeneration()'
setInterval() 可能更适合您正在做的事情并且更易于维护。
Firefox 的“错误控制台”对于调试 JavaScript 错误有很大帮助。
Patching it with this should get it running at least; it does on my system.
你的逻辑错误是你在循环过程中杀死了细胞;当代码到达应该变得活跃的死亡细胞时,您已经杀死了它的一个或多个邻居。
there's no function 'renderNextGeneration()'
setInterval() might be more appropriate and maintainable for what you're doing.
Firefox's 'error console' is a great help in debugging javascript errors.
Patching it with this should get it running at least; it does on my system.
Your logic error is that you are killing off cells as you go through the loop; by the time the code reaches the dead cell that should become alive, you've already killed one or more of its neighbors.