无论是否使用封闭,John Conways Game of Life(To use closures or not, John Conways Game of Life)

编程入门 行业动态 更新时间:2024-10-23 23:24:26
无论是否使用封闭,John Conways Game of Life(To use closures or not, John Conways Game of Life)

我目前正在制作一个游戏,说明John Conways的“生命游戏”我一直在学习关闭和模块化模式,并且正在尝试实现我在Javascript中学到的更多内容。 如果您有兴趣,可以在这里查看我的回购。 所有这些方法都在'Game'对象中。 我有它的工作,但我试图限制变量,使其尽可能的功能(在函数之间传递网格数组)。 我想要一些建议,我应该保持更高的范围变量不变或更重要。

在结构方面哪种解决方案更好?

// initial grid // will be bigger than this but is 3x3 for this question. let grid = [ [1,0,0], [0,1,0], [0,0,1] ]

解决方案1:我最初的解决方法:

function nextGrid(){ grid = applyRules(grid) renderGrid(grid) } function applyRules(grid){ // makes changes } function renderGrid(grid){ // makes changes } // call nextGrid() to generate subsequent new grids.

解决方案2:更多地研究闭包,这样更好吗?

function nextGrid() { let prevGrid = grid; return function(){ prevGrid = applyRules(prevGrid) renderGrid(prevGrid) } } function applyRules(prevGrid){ // makes changes } function renderGrid(grid){ // makes changes } const next = nextGrid(); // call next() to generate subsequent new grids.

I am currently making a game that illustrates John Conways 'Game of Life' I've been learning about closures and the modular patterns and am trying to implement more of what I'm learning in Javascript. You can check out my repo here if your interested. All of these methods are inside a 'Game' object. I have it working, but am trying to limit variables and make it as functional as possible (passing the grid array between functions). I would like some advice on wether I should be keeping higher scope variable immutable or wether it doesnt matter.

Which solution is better practise, in terms of structure?

// initial grid // will be bigger than this but is 3x3 for this question. let grid = [ [1,0,0], [0,1,0], [0,0,1] ]

Solution 1: My initial way of solving:

function nextGrid(){ grid = applyRules(grid) renderGrid(grid) } function applyRules(grid){ // makes changes } function renderGrid(grid){ // makes changes } // call nextGrid() to generate subsequent new grids.

Solution 2: Having looked into closures more, is this better?

function nextGrid() { let prevGrid = grid; return function(){ prevGrid = applyRules(prevGrid) renderGrid(prevGrid) } } function applyRules(prevGrid){ // makes changes } function renderGrid(grid){ // makes changes } const next = nextGrid(); // call next() to generate subsequent new grids.

最满意答案

你的解决方案都采用突变。 在您的第一个解决方案中,您将改变全局变量grid 。 在第二个解决方案中,您将改变局部变量prevGrid 。 一个真正有用的程序将使用递归而不是变异。 例如,这就是我要做的:

const game = /* initial game state */;

play(game);

function play(game) {
    render(game);
    setTimeout(play, 100, update(game));
}
 

正如您所看到的,我们不是改变全局变量game ,而是每100毫秒调用一次更新的游戏状态。 我们在第三行的初始通话play(game)开始游戏。 如果我们将其评论出来,则不会显示任何内容。


以下是几行代码中Conway生命游戏的完整示例:

const glyph = [" ", "■"];

document.querySelectorAll("pre.life").forEach(e => play(e, read(e.innerHTML)));

function read(text) {
    return text.split("\n").map(l => l.split("").map(c => glyph.indexOf(c)));
}

function play(pre, game) {
    pre.innerHTML = show(game);
    setTimeout(play, 100, pre, update(game));
}

function show(game) {
    return game.map(line => line.map(cell => glyph[cell]).join("")).join("\n");
}

function update(game) {
    return game.map((line, i) => line.map((cell, j) => {
        const back = game[i - 1], next = game[i + 1], h = j - 1, k = j + 1;

        const neighbors = (back && back[h] || 0)
                        + (back && back[j] || 0)
                        + (back && back[k] || 0)
                        + (line[h] || 0)
                        + (line[k] || 0)
                        + (next && next[h] || 0)
                        + (next && next[j] || 0)
                        + (next && next[k] || 0);

        switch (neighbors) {
        case 3:  return 1;
        case 2:  return cell;
        default: return 0;
        }
    }));
} 
  
pre.life {
    line-height: 0.666;
} 
  
<pre class="life">
                                      
                         ■            
                       ■ ■            
             ■■      ■■            ■■ 
            ■   ■    ■■            ■■ 
 ■■        ■     ■   ■■               
 ■■        ■   ■ ■■    ■ ■            
           ■     ■       ■            
            ■   ■                     
             ■■                       
                                      
                                      
                                      
                                      
                                      
                                      
                                      
                                      
                                      
                                      
                                      
                                      
                                      
                                       </pre> 
  
 

以上模式是Gosper滑翔机枪 。

Both your solutions employ mutation. In your first solution you mutate the global variable grid. In your second solution you mutate the local variable prevGrid. A truly functional program would use recursion instead of mutation. For example, this is what I'd do:

const game = /* initial game state */;

play(game);

function play(game) {
    render(game);
    setTimeout(play, 100, update(game));
}
 

As you can see, instead of mutating the global variable game we call play with an updated game state every 100 milliseconds. Our initial call play(game) on the third line starts the game. If we comment it out, nothing will be displayed.


Here's a complete example of Conway's Game of Life in a few lines of code:

const glyph = [" ", "■"];

document.querySelectorAll("pre.life").forEach(e => play(e, read(e.innerHTML)));

function read(text) {
    return text.split("\n").map(l => l.split("").map(c => glyph.indexOf(c)));
}

function play(pre, game) {
    pre.innerHTML = show(game);
    setTimeout(play, 100, pre, update(game));
}

function show(game) {
    return game.map(line => line.map(cell => glyph[cell]).join("")).join("\n");
}

function update(game) {
    return game.map((line, i) => line.map((cell, j) => {
        const back = game[i - 1], next = game[i + 1], h = j - 1, k = j + 1;

        const neighbors = (back && back[h] || 0)
                        + (back && back[j] || 0)
                        + (back && back[k] || 0)
                        + (line[h] || 0)
                        + (line[k] || 0)
                        + (next && next[h] || 0)
                        + (next && next[j] || 0)
                        + (next && next[k] || 0);

        switch (neighbors) {
        case 3:  return 1;
        case 2:  return cell;
        default: return 0;
        }
    }));
} 
  
pre.life {
    line-height: 0.666;
} 
  
<pre class="life">
                                      
                         ■            
                       ■ ■            
             ■■      ■■            ■■ 
            ■   ■    ■■            ■■ 
 ■■        ■     ■   ■■               
 ■■        ■   ■ ■■    ■ ■            
           ■     ■       ■            
            ■   ■                     
             ■■                       
                                      
                                      
                                      
                                      
                                      
                                      
                                      
                                      
                                      
                                      
                                      
                                      
                                      
                                       </pre> 
  
 

The above pattern is the Gosper glider gun.

更多推荐

本文发布于:2023-07-16 09:58:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1126846.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:Conways   John   Game   closures   Life

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!