美文网首页js css html
编写生命游戏

编写生命游戏

作者: 大龙10 | 来源:发表于2022-07-22 07:02 被阅读0次

    书名:代码本色:用编程模拟自然系统
    作者:Daniel Shiffman
    译者:周晗彬
    ISBN:978-7-115-36947-5
    第7章目录

    7.7 编写生命游戏

    1、用二维数组表示细胞状态

    • 现在,我们需要将之前的Wolfram CA扩展到二维空间。前面我们用一维数组存放细胞的状态,在生命游戏中,我们需要用二维数组表示细胞状态。
    int [][] board = new int[columns][rows];
    
    • 首先,我们用随机的状态值(0或1)初始化board数组中的每个细胞。
    for (int x = 0; x < columns; x++) {
        for (int y = 0; y < rows; y++) {
              current[x][y] = int(random(2)); 用0或1初始化每个细胞
        }
    }
    

    2、计算下一次迭代

    • 为了计算下一次迭代,就像以前一样,我们需要一个新的二维数组。并在遍历过程中将新状态写入这个数组。
    int[][] next = new int[columns][rows];
    for (int x = 0; x < columns; x++) {
          for (int y = 0; y < rows; y++) {
                next[x][y] = _________?; 为每个细胞设置新状态
          }
    }
    

    3、如何引用邻居细胞

    • 在研究新状态的计算方法之前,我们要先搞清楚如何引用邻居细胞。
    • 在一维CA中,引用邻居细胞很简单:如果细胞的下标是i,那么邻居的下标就是i-1和i+1。
    • 在二维CA中,每个细胞都有两个下标:列下标x和行下标y。如图7-27所示,细胞的邻居分别为:(x-1,y-1)、(x,y-1)、(x+1,y-2)、(x-1,y)、(x+1,y)、(x-1,y+1)、(x,y+1)和(x+1,y+1)。


    4、邻居数变量

    • 在生命游戏中,所有规则都只涉及“活着”的邻居细胞的数量。因此,我们可以引入一个邻居计数器变量,每次发现一个“活着”的邻居,就递增这个变量,最后就能得到“活着”的邻居的总数。
    int neighbors = 0;
    if (board[x-1][y-1] == 1) neighbors++; 最顶行的邻居
    if (board[x ][y-1] == 1) neighbors++;
    if (board[x+1][y-1] == 1) neighbors++;
    if (board[x-1][y] == 1) neighbors++; 中间的邻居(不包括自身)
    if (board[x+1][y] == 1) neighbors++;
    if (board[x-1][y+1] == 1) neighbors++; 最底行的邻居
    if (board[x ][y+1] == 1) neighbors++;
    if (board[x+1][y+1] == 1) neighbors++;
    
    • 如同Wolfram CA,上面的实现方式在教学方面非常有用,它让我们看到了每一个计算步骤(每次找到一个状态为1的邻居,就递增计数器)。但是,“如果细胞状态等于1,则让计数器加1”和“计数器加上细胞状态”这两种描述是等价的,只是后者比前者更巧妙。毕竟,如果细胞只有0和1两个状态,所有邻居细胞状态的和就等于“活着”的邻居的总数。由于邻居处在一个3 × 3的网格内,我们可以把这一步放到另一个循环中。
    for (int i = -1; i <= 1; i++) {
        for (int j = -1; j <= 1; j++) {
            neighbors += board[x+i][y+j]; 将所有邻居的状态相加
        }
    }
    
    • 上面的代码中有一个错误,在生命游戏中,细胞并不是自己的邻居。因此我们应该加一个条件判断语句:如果i和j同时等于0,则跳过当前邻居;但还有另一种方案,就是在结束循环时再减去自身的状态。
    neighbors -= board[x][y]; 减去自身的状态,我们不想把自身也包括在内
    

    5、确定新状态

    • 最后,一旦知道“活着”邻居的总数,我们下一步要做的就是确定细胞的新状态,也就是实现生命游戏的规则:新生、死亡或者静止。
    if ((board[x][y] == 1) && (neighbors < 2)) { 如果细胞活着,但活着的邻居少于两个,它就因孤next[x][y] = 0;
      }
      else if ((board[x][y] == 1) && (neighbors > 3)) { 如果细胞活着,但活着的邻居多于3个,它就next[x][y] = 0;
      }
      else if ((board[x][y] == 0) && (neighbors == 3)) { 如果细胞的状态为死亡,但它有3个活着的next[x][y] = 1;
      }
      else { 其他情况下,细胞的状态保持不变
        next[x][y] = board[x][y];
    }
    

    6、显示

    下一代状态计算完成后,我们就可以用之前的方法绘制生命游戏——黑色方块代表“活着”,白色方块代表“死亡”。

    for ( int i = 0; i < columns;i++) {
        for ( int j = 0; j < rows;j++) {   如果状态=1,就绘制黑色方块
              if ((board[i][j] == 1)) fill(0);
                else fill(255); 如果状态为0,就绘制白色方块
            stroke(0);
          rect(i*w, j*w, w, w);
        }    
    }
    

    7、结果

    相关文章

      网友评论

        本文标题:编写生命游戏

        本文链接:https://www.haomeiwen.com/subject/gheeirtx.html