使用在 JavaScript 中实现康威的生命游戏

发布于 2024-09-09 12:35:57 字数 4079 浏览 0 评论 0原文

我在用 JavaScript 实现 Conway 的生命游戏时遇到了一些问题。在德语维基百科中,它说这种模式在这里:

无法找到图片

54代后将创建一个空世界,演变如下:

找不到图片

也就是说,第二代看起来像这样:

图片无法找到

但是当使用我的代码时,第二代看起来像这样,世界也没有变空:

无法找到图片

所以我的代码显然是错误的,但我没有看到我的错误:

var cellSize = 5,   // In px
    fieldSize = 70, // In cells
    canvas = document.getElementById("canvas"),
    ctx = canvas.getContext("2d"),
    thisGeneration = [],
    nextGeneration = [];

// Set canvas size
canvas.width = canvas.height = cellSize * fieldSize;


// Fill the generation array
for (var i = 0; i < fieldSize; i++){

    thisGeneration.push([]);

    for (var x = 0; x < fieldSize; x++){

        // thisGeneration[thisGeneration.length-1].push( (Math.random() >  0.08)? 0 : 1);

        thisGeneration[thisGeneration.length-1].push(0);

    }

}

// Draw pattern:

thisGeneration[35][35]      =   thisGeneration[35][36]  = thisGeneration[35][37] =

thisGeneration[36][35]                                  = thisGeneration[36][37] =
thisGeneration[37][35]                                  = thisGeneration[37][37] =


thisGeneration[39][35]                                  = thisGeneration[39][37] =
thisGeneration[40][35]                                  = thisGeneration[40][37] =
thisGeneration[41][35]      =   thisGeneration[41][36]  = thisGeneration[41][37] =
1;

// "slice" causes "nextGeneration" to be a copy, not a reference
nextGeneration = thisGeneration.slice(0);

setInterval(function(){

    for (var y = 0, l = thisGeneration.length, x, l2, n; y < l; y++){

        for (x = 0, l2 = thisGeneration[y].length;  x < l2; x++){

            ctx.fillStyle = thisGeneration[y][x]? "black" : "white";
            ctx.fillRect(x*cellSize, y*cellSize, cellSize, cellSize);

            // n := Number of neighbors of the cell
            n = 0;

            if (typeof (thisGeneration[y-1]) != "undefined"){

                n += (

                    (thisGeneration     [y-1]   [x-1]   ||0)+
                    (thisGeneration     [y-1]   [ x ]   ||0)+
                    (thisGeneration     [y-1]   [x+1]   ||0)

                );

            }

            n += (

                (thisGeneration     [ y ]   [x-1]   ||0)+
                (thisGeneration     [ y ]   [x+1]   ||0)

            );

            if (typeof (thisGeneration[y+1]) != "undefined"){

                n += (

                    (thisGeneration     [y+1]   [x-1]   ||0)+
                    (thisGeneration     [y+1]   [ x ]   ||0)+
                    (thisGeneration     [y+1]   [x+1]   ||0)

                );

            }

            if (n === 3 && !thisGeneration[y][x]){
            // Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.

                nextGeneration[y][x] = 1;

            }

            if (n < 2 && thisGeneration[y][x]){
            // Any live cell with fewer than two live neighbours dies, as if caused by under-population.

                nextGeneration[y][x] = 0;

            }

            if ((n === 2 || n === 3) && thisGeneration[y][x]){
            // Any live cell with two or three live neighbours lives on to the next generation.

                nextGeneration[y][x] = 1;

            }

            if (n > 3 && thisGeneration[y][x]){
            // Any live cell with more than three live neighbours dies, as if by overcrowding.

                nextGeneration[y][x] = 0;

            }

        }

    }

    thisGeneration = nextGeneration.slice(0); // "slice" causes "thisGeneration" to be a copy, not a reference

}, 1000);

我还想知道是否可以提高脚本的性能,因为你可以看到我使用二维数组保存单元格状态。

I've got some problems implementing Conway's Game of Life in JavaScript. At the German Wikipedia it says that this pattern here:

image could not be found

Will create an empty world after 54 generations and the evolution looks like this:

image could not be found

That means, the second generation looks like this:

image could not be found

But when using my code, the second generation looks like this and the world doesn't get empty, either:

image could not be found

So my code is obviously wrong, but I don't see my mistake:

var cellSize = 5,   // In px
    fieldSize = 70, // In cells
    canvas = document.getElementById("canvas"),
    ctx = canvas.getContext("2d"),
    thisGeneration = [],
    nextGeneration = [];

// Set canvas size
canvas.width = canvas.height = cellSize * fieldSize;


// Fill the generation array
for (var i = 0; i < fieldSize; i++){

    thisGeneration.push([]);

    for (var x = 0; x < fieldSize; x++){

        // thisGeneration[thisGeneration.length-1].push( (Math.random() >  0.08)? 0 : 1);

        thisGeneration[thisGeneration.length-1].push(0);

    }

}

// Draw pattern:

thisGeneration[35][35]      =   thisGeneration[35][36]  = thisGeneration[35][37] =

thisGeneration[36][35]                                  = thisGeneration[36][37] =
thisGeneration[37][35]                                  = thisGeneration[37][37] =


thisGeneration[39][35]                                  = thisGeneration[39][37] =
thisGeneration[40][35]                                  = thisGeneration[40][37] =
thisGeneration[41][35]      =   thisGeneration[41][36]  = thisGeneration[41][37] =
1;

// "slice" causes "nextGeneration" to be a copy, not a reference
nextGeneration = thisGeneration.slice(0);

setInterval(function(){

    for (var y = 0, l = thisGeneration.length, x, l2, n; y < l; y++){

        for (x = 0, l2 = thisGeneration[y].length;  x < l2; x++){

            ctx.fillStyle = thisGeneration[y][x]? "black" : "white";
            ctx.fillRect(x*cellSize, y*cellSize, cellSize, cellSize);

            // n := Number of neighbors of the cell
            n = 0;

            if (typeof (thisGeneration[y-1]) != "undefined"){

                n += (

                    (thisGeneration     [y-1]   [x-1]   ||0)+
                    (thisGeneration     [y-1]   [ x ]   ||0)+
                    (thisGeneration     [y-1]   [x+1]   ||0)

                );

            }

            n += (

                (thisGeneration     [ y ]   [x-1]   ||0)+
                (thisGeneration     [ y ]   [x+1]   ||0)

            );

            if (typeof (thisGeneration[y+1]) != "undefined"){

                n += (

                    (thisGeneration     [y+1]   [x-1]   ||0)+
                    (thisGeneration     [y+1]   [ x ]   ||0)+
                    (thisGeneration     [y+1]   [x+1]   ||0)

                );

            }

            if (n === 3 && !thisGeneration[y][x]){
            // Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.

                nextGeneration[y][x] = 1;

            }

            if (n < 2 && thisGeneration[y][x]){
            // Any live cell with fewer than two live neighbours dies, as if caused by under-population.

                nextGeneration[y][x] = 0;

            }

            if ((n === 2 || n === 3) && thisGeneration[y][x]){
            // Any live cell with two or three live neighbours lives on to the next generation.

                nextGeneration[y][x] = 1;

            }

            if (n > 3 && thisGeneration[y][x]){
            // Any live cell with more than three live neighbours dies, as if by overcrowding.

                nextGeneration[y][x] = 0;

            }

        }

    }

    thisGeneration = nextGeneration.slice(0); // "slice" causes "thisGeneration" to be a copy, not a reference

}, 1000);

I'd also like to know whether I could improve the performance of the script, because as you can see I use a 2-dimensional array save the cell states.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

¢好甜 2024-09-16 12:36:00

我不认为这一代和下一代像你想象的那样独立。我建议您用逐个单元复制替换切片操作,看看是否可以解决问题。

I don't think that thisGeneration and nextGeneration are as independent as you think they are. I suggest you replace the slice operations with a cell by cell copy and see if that resolves things.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文