【问题标题】:Implementation of Conway's Game of Life in Javascript - Cellular logic issues在 Javascript 中实现 Conway 的生命游戏 - 蜂窝逻辑问题
【发布时间】:2023-03-28 01:04:01
【问题描述】:

我决定编写自己的 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);

}

【问题讨论】:

    标签: javascript dhtml


    【解决方案1】:

    没有函数'renderNextGeneration()'

    setInterval() 可能更适合您正在做的事情且可维护。

    Firefox 的“错误控制台”对调试 javascript 错误有很大帮助。


    用这个修补它至少应该让它运行;它在我的系统上。
    jcomeau@intrepid:~/stackoverflow/gameoflife$ bzr diff -r18 bad.js
    === modified file 'gameoflife/bad.js'
    --- gameoflife/bad.js   2011-05-15 14:09:12 +0000
    +++ gameoflife/bad.js   2011-05-16 04:14:40 +0000
    @@ -1,10 +1,11 @@
    -var chanceOfLiveCells = 0.1;
    +var chanceOfLiveCells = 0.0;
     var gridReference = null;
     var gridDimension = 15;
     var cells = null;
     var cellsAlive = 0;
     var cellsDead = 0;
     var currentGeneration = 0;
    +var timer = null;
    
     function init() {
    
    @@ -13,7 +14,8 @@
    
         drawGrid();
         placeRandomCells();
    -    nextGeneration();
    +    createBlinker();
    +    timer = setInterval(nextGeneration, 200);
    
     }
    
    @@ -45,7 +47,7 @@
     }
    
     function nextGeneration() {
    -
    +    alert("next generation");
         currentGeneration = currentGeneration + 1;
    
         for(var x = 0; x <= gridDimension - 1; x = x + 1) {
    @@ -93,15 +95,16 @@
             }
    
         }
    -
    +    
    +    repaint();
         document.getElementById('currentGeneration').innerHTML = currentGeneration;
         document.getElementById('cellsAlive').innerHTML = cellsAlive;
         document.getElementById('cellsDead').innerHTML = cellsDead;
    +    if (cellsAlive == 0) clearInterval(timer);
    
         cellsAlive = 0;
         cellsDead = 0;
    
    -    setTimeout('nextGeneration()', 200);
    
     }
    
    @@ -127,17 +130,40 @@
    
         }
    
    +    repaint();
    +
    +}
    +function repaint() {
    +
    +    for(var x = 0; x <= gridDimension - 1; x = x + 1) {
    +
    +        for(var y = 0; y <= gridDimension - 1; y = y + 1) {
    +
    +            repaintCell(x, y);
    +
    +        }
    +
    +    }
    +
    +}
    +
    +function repaintCell(x, y) {
    +
    +    cell = document.getElementById(getCell(x, y));
    +    color = cell.style.color;
    +    cell.style.backgroundColor = color;
    +
     }
    
     function setLiveCell(x, y) {
    
    -    document.getElementById(getCell(x, y)).style.backgroundColor = 'red';
    +    document.getElementById(getCell(x, y)).style.color = 'red';
    
     }
    
     function setDeadCell(x, y) {
    
    -    document.getElementById(getCell(x, y)).style.backgroundColor = 'maroon';
    +    document.getElementById(getCell(x, y)).style.color = 'maroon';
    
     }
    
    @@ -249,7 +275,7 @@
         setLiveCell(6, 5);
         setLiveCell(6, 4);
         setLiveCell(5, 4);
    -
    +    repaint()
     }
    
     function createBlinker() {
    @@ -257,7 +283,7 @@
         setLiveCell(4, 5);
         setLiveCell(5, 5);
         setLiveCell(6, 5);
    -
    +    repaint();
     }
    
     function createBeacon() {
    @@ -270,5 +296,5 @@
         setLiveCell(6, 7);
         setLiveCell(7, 6);
         setLiveCell(7, 7);
    -
    +    repaint();
     }
    

    你的逻辑错误是你在循环过程中杀死了细胞;当代码到达应该变得活跃的死细胞时,你已经杀死了它的一个或多个邻居。

    【讨论】:

    • 假设是 nextGeneration()
    • 我不会说这是错误,更多的是逻辑问题,所以错误控制台没用。
    • 今天早上做了一点测试,并发布了一个补丁。
    • 逻辑有问题。我试图模拟的规则是: - 如果任何活细胞的相邻细胞少于两个,它就会死亡。 - 如果任何活细胞恰好有两个或三个相邻细胞,它就会存活。 - 如果任何活细胞的相邻细胞超过三个,它就会死亡。 - 如果任何死细胞恰好有三个活的相邻细胞,它就会变成活的。我已经测试了所有这些规则,唯一一个似乎不完全按照它应该的方式工作的是第四条规则。您假定的补丁仍然具有相同的行为。
    • 那么,简而言之,你将如何阻止它杀死相邻的细胞?停止计时器?我有点困惑。感谢您的帮助,jcomeau_ictx。
    猜你喜欢
    • 1970-01-01
    • 2013-12-01
    • 2019-07-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-09
    • 2016-04-05
    • 2023-02-08
    相关资源
    最近更新 更多