生命游戏

1,061 阅读3分钟

生命游戏(Game of Life)是由约翰·何顿·康威(John Horton Conway)设计的计算机程序。它按照一定的规律逐代演化,模拟了生命的出生、繁衍和消亡过程。根据初始结构的不同,在演化过程中有时能呈现出一定规律性,有时则显得杂乱无章,体验地址

它用一张二维网格来模拟二维世界,网格中的格子就代表“细胞”,每个细胞只有两种状态:存活或死亡。每隔一段时间,细胞将迭代一轮,下一轮的细胞状态由上一轮该细胞周围的细胞状态决定。决定细胞状态的规则是:

  • 当前细胞为存活状态时,当周围的存活细胞低于2个时(不包含2个),该细胞变成死亡状态。(模拟生命数量稀少)
  • 当前细胞为存活状态时,当周围有2个或3个存活细胞时,该细胞保持原样。
  • 当前细胞为存活状态时,当周围有超过3个存活细胞时,该细胞变成死亡状态。(模拟生命数量过多)
  • 当前细胞为死亡状态时,当周围有3个存活细胞时,该细胞变成存活状态。(模拟繁殖)

这些规则清晰明了,非常适合用程序语言来描述,下面,就让我们一起来使用 pixi.js 来完成这个简单的小游戏,亲身体验它的奇妙变化吧!

初始化棋盘

创建pixi.js 的 application 并添加到 dom 中,我这里使用的 vue 的 ref,画出长宽一样的区域,这片区域是纯黑色的

  const settingStore = useSettingStore();
  app = new Application();
  await app.init({
    width: settingStore.rowNumber * settingStore.gridLength, // 40*20
    height: settingStore.rowNumber * settingStore.gridLength
  });
  refValue.appendChild(app.canvas);

接下来,画出底色小方格:

  const stateStore = useStateStore();
  const settingStore = useSettingStore();
  // 小方格在没开始的时候可以点击切换状态
  const onClick = (event) => {
    if (!stateStore.hasBegin) {
      changeCellState(event.target);
    }
  };
  for (let i = 0; i < settingStore.rowNumber; i++) {
    const row = [];
    cells.push(row);
    for (let j = 0; j < settingStore.rowNumber; j++) {
      // 创建一个细胞
      const cell = new Graphics();

      // 底色使用两种颜色
      const bgColor = (i + j) % 2 === 0 ? '#87B990' : '#7eb187';
      // 画一个矩形,作为一个细胞
      cell.rect(0, 0, settingStore.gridLength, settingStore.gridLength);
      // 设置细胞的颜色
      cell.fill(bgColor);
      // 设置细胞的位置
      cell.position.x = settingStore.gridLength * i;
      cell.position.y = settingStore.gridLength * j;
      // 添加事件反馈,否则没有点击事件
      cell.interactive = true;
      // 细胞的状态
      cell.isLive = false;
      // 细胞上一个状态的颜色
      cell.beforeColor = '#1e5428';
      // 细胞的点击事件
      cell.on('pointerdown', onClick);
      // 将细胞添加进画布
      app.stage.addChild(cell);
      row.push(cell);
    }
  }

每个细胞都添加了一个初始的状态 isLive,添加了一个点击事件的处理(可以让我们在未开始之前随意调整细胞布局)

运行

根据游戏规则,我们知道一个细胞下一周期的状态,取决于当前周期此细胞周围 8 个细胞的状态,那么我们就:

  1. 获取当前细胞的状态矩阵
  2. 获取当前细胞周围存活细胞数的矩阵
  3. 根据规则,获取下一个周期的细胞状态,并修改细胞状态

接下来就是按照一定的周期去运行以上的逻辑,直接使用 setInterval 就好了

经典的图像

一般的情况下,细胞会呈现规则的扩散,但也有一些经典的图像

稳定态

震荡态

移动态

源码

源码