JavaScript 实现生命游戏

目录
  • 概念介绍
  • 逻辑规则
  • 完整代码
  • 主要实现

概念介绍

元胞自动机(Cellular Automata),是 20 世纪 50 年代初由计算机之父冯·诺依曼(John von Neumann)为了模拟生命系统所具有的自复制功能而提出来的。

生命游戏(Game of Life),或者叫它的全称 John Conway's Game of Life,是英国数学家约翰·康威在 1970 年代所发明的一种元胞自动机。

逻辑规则

在二维平面方格里,每个细胞有两种状态:存活或死亡,而下一时刻的状态完全受它周围 8 个细胞的状态而定。

这个世界有三条演化规则:

  1. 当周围有 2 个存活细胞时,该细胞生命状态保持原样;
  2. 当周围有 3 个存活细胞时,该细胞为存活状态(死亡细胞会复活);
  3. 当周围存活细胞低于 2 个时(生命数量稀少)或周围超过 3 个存活细胞时(生命数量过多),该细胞为死亡状态。

完整代码

焚霜 / LifeGame

演示页面

基本结构

index.html   // 主页面,初始化系统,控制系统运行等
canvas.js    // 渲染层,创建画布,手动绘制,画布更新方法等
LifeGame.js  // 逻辑层,创建运行系统,系统运行逻辑,数据更新等

主要实现

系统配置:定义二维平面方格尺寸,data 中以 key,value 形式存储了所有细胞的生命状态,execute 是 canvas.js 暴露出来的内部方法,挂载到 config 对象上。

  const config = {
    width: 100, // 横向细胞数量
    height: 100, // 纵向细胞数量
    size: 4 + 1, // 细胞大小,细胞间距 1px
    speed: 200, // 细胞迭代速度
    alive: '#000000', // 细胞存活颜色
    dead: '#FFFFFF', // 世界颜色(细胞死亡颜色)
    data: new Map(), // 系统运行数据
    execute, // 更新画布方法
  };

规则实现:遍历二维平面里每个细胞,拿到当前的细胞状态,计算其周围存活细胞的数量,判断其下一时刻是存活还是死亡,并将这个状态保存下来,通过调用渲染层的更新画布方法 execute 来更新界面显示。这里在处理 data 数据时没有用二维数组表示二维坐标系,而是将其转换为一维线性表示,将数据保存在 Map 中。

  // LifeGame.js

  // 二维坐标系一维线性表示
  const MakeKey = (x = 0, y = 0) => y * 10000 + x;

  function refreshWorld() {
    const next = new Map(); // 更新后的系统运行数据
    // 迭代二维坐标系所有元素
    IterateCells(config, (x, y) => {
      const index = MakeKey(x, y); // 计算坐标对应的 key
      const current = config.data.get(index); // 当前细胞状态
      // 计算当前细胞周围存活细胞的数量
      switch (borderSum(x, y)) {
        case 2:
          // 当周围有 2 个存活细胞时,该细胞保持原样。
          next.set(index, current);
          break;
        case 3:
          // 当周围有 3 个存活细胞时,该细胞为存活状态。
          next.set(index, true);
          !current && config.execute(x, y, true); // 状态变化,更新画布
          break;
        default:
          // 当周围的存活细胞低于 2 个时,该细胞为死亡状态。(生命数量稀少)
          // 当周围有超过 3 个存活细胞时,该细胞为死亡状态。(生命数量过多)
          next.set(index, false);
          current && config.execute(x, y, false); // 状态变化,更新画布
          break;
      }
      return true;
    });
    return next;
  }

系统的启动与停止

  // LifeGame.js

  // 开启系统
  function startWorld() {
    stopWorld(); // 停止之前启动的循环
    // 根据迭代速度启动系统,循环更新系统
    interval = setInterval(() => (config.data = refreshWorld()), config.speed || 500);
    starting = true; // 开启启动标识
    return true;
  }

  // 关闭系统,当前系统运行数据保留
  function stopWorld() {
    clearInterval(interval); // 停止循环
    starting = false; // 关闭启动标识
    return true;
  }

计算存活细胞方法

  // LifeGame.js

  function borderSum(x = 0, y = 0) {
    const { width, height, data } = config;
    let sum = 0;
    for (let j = y - 1; j <= y + 1; j++) {
      for (let i = x - 1; i <= x + 1; i++) {
        // 边界判断
        if (i < 0 || j < 0 || i >= width || j >= height || (i === x && j === y)) {
          continue;
        }
        if (data.get(MakeKey(i, j))) {
          sum++; // 存活细胞数量累加
        }
      }
    }
    return sum;
  }

迭代二维坐标系方法

/**
 * 迭代二维坐标系所有元素,执行回调函数
 * @param config: { width: number, height: number }
 * @param callback: (x: number, y: number) => boolean
 */
const IterateCells = ({ width, height }, callback) => {
  for (let y = 0; y < height; y++) {
    for (let x = 0; x < width; x++) {
      if (callback && !callback(x, y)) {
        return false;
      }
    }
  }
  return true;
};

更新画布方法

  // canvas.js

  function execute(x, y, life) {
    const { size, alive, dead } = config;
    // 设置细胞颜色
    context.fillStyle = life ? alive : dead;
    // 绘制细胞,细胞间距 1px
    context.fillRect(x * size + 1, y * size + 1, size - 1, size - 1);

    return true;
  }

以上就是JavaScript 实现生命游戏的详细内容,更多关于JavaScript 生命游戏的资料请关注我们其它相关文章!

(0)

相关推荐

  • 基于JavaScript实现简单扫雷游戏

    对于10年前的人来说,扫雷肯定是家喻户晓,由于当时的科技并不是很发达,大家对于电脑游戏的了解,可能都是从扫雷开始的,今天就交大家一种用js原生代码写一个简单的扫雷游戏,话不多说,直接上干货: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="wid

  • js实现贪吃蛇游戏含注释

    本文实例为大家分享了js实现贪吃蛇游戏的具体代码,供大家参考,具体内容如下 两个小时完成的,有点简陋. 直接看效果.打开调试面板,在resource面板,新建snippet 粘贴以下代码,右键snippet,run. clearInterval(timer); document.body.innerHTML = ""; //每秒移动多少格 let speed = 10; let speedUpMul = 3; //是否能穿墙 let isThroughTheWall = true; /

  • 原生js实现2048小游戏

    2048小游戏,供大家参考,具体内容如下 首先2048小游戏离不开16个格子,我们通过html和css创建好对应的标签和样式,然后开始js逻辑 <div id="box">//一个盒子里面16个小div <div id="son"></div> <div id="son"></div> <div id="son"></div> <div

  • 用js实现拼图小游戏

    本文实例为大家分享了js实现拼图小游戏的具体代码,供大家参考,具体内容如下 一.js拼图是什么? 用js做得小游戏 二.使用步骤 1.先创建div盒子 <style> div,body{ margin: 0; height: 0; } #box{ width: 800px; height: 800px; background-color: burlywood; position: relative; } #box div { width: 200px; height: 200px; backg

  • javascript实现拼图游戏

    本文实例为大家分享了javascript实现拼图游戏的具体代码,供大家参考,具体内容如下 <div id="container"> <!--最外面的DIV,用来包含里面的结构--> <div id="game"> <!--游戏区,大DIV方块--> <div id="d1" onclick="move(1)">1</div> <!--小DIV,也就是

  • JavaScript实现打字游戏

    本文实例为大家分享了JavaScript实现打字游戏的具体代码,供大家参考,具体内容如下 效果图: 需求分析: 1.在char这个div里面显示要输入的字母,大写 2.在result这个div里面时时显示正确率,比如98% 3.给文档绑定按键事件 4.如果输入的内容和char里面一致,显示正确动画:animated zoomIn,并更换输入的字母 5.如果输入的内容和char里面不一致,显示错误动画:animated shake error 6.不管是正确还是错误都时时更新result里面的正确

  • 原生js实现自定义难度的扫雷游戏

    本文实例为大家分享了js实现扫雷游戏的具体代码,供大家参考,具体内容如下 游戏功能: 1.有四个难度 2.可以自定难度 1.html相关代码 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-

  • 如何利用JavaScript编写一个格斗小游戏

    拖延症晚期的我原本计划趁着周末写个年终总结,但是一直没有什么思路,想来想去也没想到要写啥就胡乱写了这么一个小东西. 一直比较痴迷游戏行业,可能我不太适合做前端,应该去学C++.... 首先当然是选择一张背景图,作为整个场景中的地图,而且要大要高清.布局到页面中. 然后通过可视区值展示这张图片的一小部分.我这里用的是宽600,高420的,超出直接隐藏掉. width: 600px; height: 420px; 这样一个简单的场景就写好了,接着我们需要在这个场景中加入我们的人物.也就是游戏中的角色

  • 原生JS实现点击数字小游戏

    原生JS实现点击数字小游戏,供大家参考,具体内容如下 最近公司在季度测试中出了一道很有趣的测试题,要求使用我们自己的黑科技–IVX来实现,感兴趣的朋友可以去了解哦,是真的黑科技,在这里我还是用原生JS来实现吧,题目是这样的: 实现一个点击数字的小游戏:依次点击容器中随机生成的数字元素,生成的数字元素会在5S后消失,你将凭借记忆点击按照数字升序依次点击生成的数字方可通过该关卡游戏. 话不多说直接看运行效果图: 上代码: <!DOCTYPE html> <html lang="en

  • JavaScript 实现生命游戏

    目录 概念介绍 逻辑规则 完整代码 主要实现 概念介绍 元胞自动机(Cellular Automata),是 20 世纪 50 年代初由计算机之父冯·诺依曼(John von Neumann)为了模拟生命系统所具有的自复制功能而提出来的. 生命游戏(Game of Life),或者叫它的全称 John Conway's Game of Life,是英国数学家约翰·康威在 1970 年代所发明的一种元胞自动机. 逻辑规则 在二维平面方格里,每个细胞有两种状态:存活或死亡,而下一时刻的状态完全受它周

  • 使用Rust制作康威生命游戏的实现代码

    目录 前言 安装准备 初始项目 Cargo.toml 初始web项目 游戏规则 游戏设计 Rust实现 测试 调试 前言 之前学了几遍,后来忘记了,通过制作该游戏再复习复习. 安装准备 wasm-pack : https://rustwasm.github.io/wasm-pack/installer/ cargo-generate: cargo install cargo-generate 初始项目 初始rust项目 使用wasm的项目模板: cargo generate --git http

  • JavaScript实现斗地主游戏的思路

    本文知识给大家分享一下使用js写斗地主的思路,代码写的不好,还请见谅. 这里说说斗地主主要包含的功能:洗牌,发牌,玩家出牌.电脑出牌,出牌规则的验证,输赢啥的没有判断,只是实现了这几个主要功能,下面依次说说几个功能的实现: 1.洗牌: var pukes=this.manage.pukes;//存放扑克牌的数组 //洗牌 for(var i=;i<pukes.length;i++){ var tmp=pukes[i]; var index=util.random(i,pukes.length);

  • JavaScript实现HTML5游戏断线自动重连的方法

    断线重连的需求一断线重连原理二游戏内自动重连不刷新三刷新游戏自动重连重连数据Locationreplace重置url重连四实际项目中处理重连机制最后的总结断线重连的需求 尤其是手机上,会因为网络的不稳定或者其他原因,导致用户的socket链接断开.这个时候如果直接让玩家退出游戏,重新登录,无疑是非常影响用户体验的事情.所以根据这个需求,就有需要程序来实现断线后自动重连回去的技术,是用户能够再次快速开始游戏进行战斗. 一.断线重连原理 原来其实很简单,就是在断线的时候,根据用户的点击(有些时间短的

  • 原生JavaScript实现连连看游戏(附源码)

    向大家推荐一款原生JavaScript版连连看游戏,源码下载,首页如下图所示:  首先看一下html的布局方式在index.html文件中: 复制代码 代码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html> <head>

  • C语言借助EasyX实现的生命游戏源码

    本文讲述C语言借助EasyX实现的生命游戏,具体操作流程如下: 1.生命游戏内容: 该游戏包括一个二维矩形世界,这个世界中的每个方格居住着一个活着的或死了的细胞.一个细胞在下一个时刻生死取决于相邻八个方格中活着的细胞的数量.如果一个细胞周围的活细胞数量多于 3 个,这个细胞会因为资源匮乏而在下一个时刻死去:如果一个位置周围有 3 个活细胞,则该位置在下一个时刻将诞生一个新的细胞:如果一个位置周围有 2 个活细胞,则该位置的细胞生死状态保持不变:如果一个细胞周围的活细胞少于 2 个,那么这个细胞会

  • 详解Python 实现元胞自动机中的生命游戏(Game of life)

    简介 细胞自动机(又称元胞自动机),名字虽然很深奥,但是它的行为却是非常美妙的.所有这些怎样实现的呢?我们可以把计算机中的宇宙想象成是一堆方格子构成的封闭空间,尺寸为N的空间就有NN个格子.而每一个格子都可以看成是一个生命体,每个生命都有生和死两种状态,如果该格子生就显示蓝色,死则显示白色.每一个格子旁边都有邻居格子存在,如果我们把33的9个格子构成的正方形看成一个基本单位的话,那么这个正方形中心的格子的邻居就是它旁边的8个格子. 每个格子的生死遵循下面的原则: 1. 如果一个细胞周围有3个细胞

  • python实现生命游戏的示例代码(Game of Life)

    生命游戏的算法就不多解释了,百度一下介绍随处可见. 因为网上大多数版本都是基于pygame,matlab等外部库实现的,二维数组大多是用numpy,使用起来学习成本比较高,所以闲暇之余写一个不用外部依赖库,console输出的版本. # -*- coding: utf-8 -*- from time import sleep from copy import deepcopy WORLD_HIGH = 20 #世界长度 WORLD_WIDE = 40 #世界宽度 ALIVE_CON = 3 #复

  • JavaScript实现五子棋游戏的方法详解

    本文实例讲述了JavaScript实现五子棋游戏的方法.分享给大家供大家参考,具体如下: 最近半个月一直在看深入的学习JavaScript,里面有很多重点和难点,比如闭包.词法分析.面向对象等.今天给大家分享一个由JavaScript编写的五子棋游戏,主要用到JavaScript的面向对象.事件委托.闭包等知识,还是挺有分量的,正好可以检测学习的成果. 老规矩,先上图,再说话. 效果图: 五子棋素材图: 代码: <!DOCTYPE html> <html> <head>

  • Python生命游戏实现原理及过程解析(附源代码)

    1. 生命游戏是什么 生命游戏是英国数学家约翰·何顿·康威在1970年发明的细胞自动机.它包括一个二维矩形世界,这个世界中的每个方格居住着一个活着的或死了的细胞.一个细胞在下一个时刻生死取决于相邻八个方格中活着的或死了的细胞的数量.如果相邻方格活着的细胞数量过多,这个细胞会因为资源匮乏而在下一个时刻死去:相反,如果周围活细胞过少,这个细胞会因太孤单而死去. 规则看起来很简单,但却能演绎出无穷无尽的内容. 滑翔者:每4个回合"它"会向右下角走一格.虽然细胞早就是不同的细胞了,但它能保持原

随机推荐