JavaScript面向对象编程小游戏---贪吃蛇代码实例


Posted in Javascript onMay 15, 2019

1 面向对象编程思想在程序项目中有着非常明显的优势:
1- 1 代码可读性高.由于继承的存在,即使改变需求,那么维护也只是在局部模块
1-2 维护非常方便并且成本较低。

​2 这个demo是采用了面向对象的编程思想. 用JavaScript 语言编写的游戏小程序--贪吃蛇.
​ 代码注释详细,逻辑清晰 . 非常适合新手前端开发者, 锻炼JavaScript语言的面向对象的编程思想. 
该小Demo已上传GitHub,欢迎下载!  觉得好的话,随手给个star,  您的star是我最大的动力!

https://github.com/XingJYGo/snakePlay#javascript-经典面向对象demo-贪吃蛇

代码展示:
代码结构:
--index.html 地图页面,展示蛇和食物,进行游戏
--food.js   构造食物对象
--game.js   构造游戏对象
--snake.js   构造蛇对象
--tool.js   常用数据工具封装

--index.html 地图页面

<!DOCTYPE html>
<html lang="zh-CN">
<head>
 <meta charset="UTF-8">
 <title>Title</title>
 <style>
  #map{
   width: 500px;
   height: 500px;
   background-color: lightblue;
   position: relative;
  }
  
 </style>
</head>
<body>
<div id="map">
 
</div>
<button id="btn">模拟蛇吃到食物</button>
<script src="tool.js"></script>
<script src="food.js"></script>
<script src="snake.js"></script>
<script src="game.js"></script>
<script>
 
////==========前后方向设定后 ==================
var game = new Game();
game.start();
 
 
 
</script>
 
</body>
</html>

--food.js   构造食物对象

// 封装一个食物对象
//沙箱模式
(function(){
 var container; //用于存储之前的食物
 function Food(option) {
  //防止用户不传参数会报错
  option = option || {};
  this.width = option.width || 20;
  this.height = option.height || 20;
  this.bgc = option.bgc || 'orange';
  this.x = option.x || 0;
  this.y = option.y || 0;
  this.borderRadius = option.borderRadius |10;
 }
 
 Food.prototype.render = function () {
  //每一次渲染新的之前就把原来的移除掉
  if(container){
   map.removeChild(container);
  }
  // 创建食物对象
  var food = document.createElement('div');
  //存到全局变量里
  container = food;
  food.style.width = this.width + 'px';
  food.style.height = this.height + 'px';
  food.style.backgroundColor = this.bgc;
  food.style.position = 'absolute';
   //获得随机位置
   //由于要让食物的位置在每一个格子里面,所有获取随机数的算法要重新计算
  this.x = Tool.getRandom(0, (map.offsetWidth/ this.width-1)) * this.width;
  this.y = Tool.getRandom(0, (map.offsetHeight/ this.height-1)) * this.height;
  food.style.left = this.x + 'px';
  food.style.top = this.y + 'px';
  food.style.borderRadius = this.borderRadius + 'px';
  //渲染上食物
  map.appendChild(food);
 }
 
 //因为要在全局使用Food,需要把Food拿到全局中
 window.Food = Food;
})();

--game.js   构造游戏对象

(function () {
//  1 由于游戏对象要控制蛇和食物,
//   所以游戏对象应该拥有蛇的实例和食物的实例
  //存储定时器的id
  var timeid;
  function Game() {
    this.snake = new Snake();
    this.food = new Food();
  }
 
  //2 开始游戏
  Game.prototype.start = function () {
    this.snake.render();
    this.food.render();
 
    // 2-1 游戏一开始,蛇和食物就渲染出来
    timeid = setInterval(function () {
      //2-2 -1 蛇的数据改变
      this.snake.move();
      // 2-3 判断蛇是否到达边界
      var snakeHead = this.snake.body[0];
      //2-3-1 求蛇头可以移动的水平/垂直坐标的最大位置
      var maxX = map.offsetWidth/this.snake.width -1;
      var maxY = map.offsetHeight/this.snake.height -1;
      if (snakeHead.x <0 ||snakeHead.x > maxX ||snakeHead.y <0 ||snakeHead.y > maxY){
        clearInterval(timeid);
        alert("gave over");
        //注:当X超出范围,代码应立即终止,
        // 防止2-2-2 渲染出下一个盒子.展示出来
        return;
      }
 
 
      //2-4 蛇吃食物
      //依据: 蛇头的坐标 和 食物的坐标重合
      var snakeX = snakeHead.x * this.snake.width;
      var snakeY = snakeHead.y * this.snake.height;
      var foodX = this.food.x;
      var foodY = this.food.y;
 
      //如果符合条件, 证明吃到了食物
       if (snakeX === foodX && snakeY === foodY){
         // 2-4-1 食物消失, 渲染新食物
         this.food.render();
         // 2-4-2 蛇,变长
         //  其实就是往snake.body.push个新对象
         //  bug: 为了解决新添加蛇节闪下的问题, 把蛇的最后一节对象,作为新的对象.
         var last = this.snake.body[this.snake.body.length -1];
         this.snake.body.push({
           x:last.x,
           y:last.y,
           col:last.col
         })
         // this.snake.body.push(last);
         // 注:last本身已经在数组中了,
       }
      //2-2 -2渲染到页面上,真正看到的蛇动起来
      this.snake.render();
 
    }.bind(this), 150)
 
    // 3 给页面注册键盘按下的事件
    // 3-1 监听用户是否按下了上,下,左,右的按键
 
    document.onkeydown = function(e){
      // console.log(this);
      e = e || window.event;
      console.log(e.keyCode);
      // 左37 上38 右39  下40
      switch(e.keyCode){
 
        case 37:
          //3-11 需要找到蛇,修改蛇的direction属性
          //防止原地掉头
          if(this.snake.direction === 'right'){
            return;
          }
          this.snake.direction = 'left';
          break;
        case 38:
          if(this.snake.direction === 'bottom'){
            return;
          }
          this.snake.direction = 'top';
          break;
        case 39:
          if(this.snake.direction === 'left'){
            return;
          }
          this.snake.direction = 'right';
          break;
        case 40:
          if(this.snake.direction === 'top') return; //如果if中只有一行代码就可以不写花括号,然后这一行代码要紧跟在if后面记得加分号
          this.snake.direction = 'bottom';
          break;
 
      }
    }.bind(this);
 
 
 
  };
 
  //2-2 蛇变量赋予全局
  window.Game = Game;
 
})();

--snake.js   构造蛇对象

(function () {
  var arr = []; //用于存储蛇的每一节数据
 
  // 1 创建蛇对象
  function Snake(option) {
    option = option || {};
    this.width = option.width || 20;
    this.height = option.height || 20;
    this.body = [
      {x: 3, y: 2, col: 'green'},//蛇头的位置和颜色
      {x: 2, y: 2, col: 'orange'},//蛇头身体的位置和颜色
      {x: 1, y: 2, col: 'orange'}];
    this.direction = option.direction || 'right';
  }
 
 
  //2 渲染蛇的方法
  Snake.prototype.render = function () {
    // 2-3 为了防止多个sanke渲染到页面上,一渲染之前先清除掉原来的
    for (var i = 0; i < arr.length; i++) {
      map.removeChild(arr[i]);//移除页面上的蛇节
    }
    arr.splice(0,arr.length);//蛇节都被移除掉了,那么数组中也应该都移除.
 
    //2-1 根据body中的个数,动态的创建蛇节
    this.body.forEach(function (item, index) {
      //2-0 动态的创建蛇节
      var snakeNode = document.createElement('div');
      //2-4 遍历添加蛇节新数据
      arr.push(snakeNode);
      snakeNode.style.width = this.width + 'px';
      snakeNode.style.height = this.height + 'px';
      snakeNode.style.position = 'absolute';
      snakeNode.style.left = item.x * this.width + 'px';
      snakeNode.style.top = item.y * this.height + 'px';
      snakeNode.style.backgroundColor = item.col;
      map.appendChild(snakeNode);
 
    }.bind(this))
    //  2-2 上面的this是在snake里面,指向snake.`
    //  否则,默认指向window
  };
 
 
 
  //3 蛇移动的方法:body 头数组赋值给身体.
  Snake.prototype.move = function () {
    //3-1 蛇后面的数据给前面
    for (var i = this.body.length -1; i >0; i--) {
      this.body[i].x = this.body[i - 1].x;
      this.body[i].y = this.body[i - 1].y;
    }
  //  3-2暂时蛇头往右走
  //   this.body[0].x +=1;
  //
  //3-2蛇头一定的位置,要根据蛇的方向来决定
    switch(this.direction){
 
      case 'left':
        this.body[0].x -= 1;
        break;
      case 'right':
        this.body[0].x += 1;
        break;
      case 'top':
        this.body[0].y -= 1;
        break;
      case 'bottom':
        this.body[0].y += 1;
        break;
    }
  };
 
 
 
  //赋予全局变量
  window.Snake = Snake;
})();

--tool.js   常用数据工具封装

//用于存放一些常用的功能性的函数
 
//  function getRandom(){
//
// }
var Tool = {
 //获取min - max之间的随机整数
 getRandom: function(min, max){
  return Math.floor(Math.random() * (max - min + 1)) + min;
 }
}
 
// Tool.getRandom()

以上所述是小编给大家介绍的JavaScript贪吃蛇的实现详解整合,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
一起来写段JS drag拖动代码
Dec 09 Javascript
JavaScript进阶练习及简单实例分析
Jun 03 Javascript
详谈Node.js之操作文件系统
Aug 29 Javascript
微信小程序中使用ECharts 异步加载数据实现图表功能
Jul 13 Javascript
jQuery md5加密插件jQuery.md5.js用法示例
Aug 24 jQuery
Vue利用History记录上一页面的数据方法实例
Nov 02 Javascript
动态内存分配导致影响Javascript性能的问题
Dec 18 Javascript
详解js获取video任意时间的画面截图
Apr 17 Javascript
微信小程序实现滚动Tab选项卡
Nov 16 Javascript
vue编写简单的购物车功能
Jan 08 Vue.js
Moment的feature导致线上bug解决分析
Sep 23 Javascript
Vue Element plus使用方法梳理
Dec 24 Vue.js
小程序绑定用户方案优化小结
May 15 #Javascript
pm2发布node配置文件ecosystem.json详解
May 15 #Javascript
JQuery常见节点操作实例分析
May 15 #jQuery
JS算法题之查找数字在数组中的索引位置
May 15 #Javascript
JQuery属性操作与循环用法示例
May 15 #jQuery
前端js中的事件循环eventloop机制详解
May 15 #Javascript
mpvue小程序循环动画开启暂停的实现方法
May 15 #Javascript
You might like
做个自己站内搜索引擎
2006/10/09 PHP
php相当简单的分页类
2008/10/02 PHP
php通过文件头检测文件类型通用代码类(zip,rar等)
2010/10/19 PHP
解析php如何将日志写进syslog
2013/06/28 PHP
PHP中常用的转义函数
2014/02/28 PHP
PHP中file_exists()判断中文文件名无效的解决方法
2014/11/12 PHP
PHP基于正则批量替换Img中src内容实现获取缩略图的功能示例
2017/06/07 PHP
Code: write(s,d) 输出连续字符串
2007/08/19 Javascript
使用jQuery UI的tooltip函数修饰title属性的气泡悬浮框
2013/06/24 Javascript
js实现图片和链接文字同步切换特效的方法
2015/02/20 Javascript
js实现简单的联动菜单效果
2015/08/19 Javascript
Highcharts使用简例及异步动态读取数据
2015/12/30 Javascript
利用jquery实现实时更新歌词的方法
2017/01/06 Javascript
轻松玩转BootstrapTable(后端使用SpringMVC+Hibernate)
2017/09/06 Javascript
微信小程序中的canvas 文字断行和省略号显示功能的处理方法
2018/11/14 Javascript
微信小程序实现简单文字跑马灯
2020/05/26 Javascript
vue 基于abstract 路由模式 实现页面内嵌的示例代码
2020/12/14 Vue.js
Python Trie树实现字典排序
2014/03/28 Python
使用Python实现下载网易云音乐的高清MV
2015/03/16 Python
Python3实现发送QQ邮件功能(html)
2017/12/15 Python
Python使用gRPC传输协议教程
2018/10/16 Python
Python 转换RGB颜色值的示例代码
2019/10/13 Python
Python模块 _winreg操作注册表
2020/02/05 Python
Python求解排列中的逆序数个数实例
2020/05/03 Python
python thrift 实现 单端口多服务的过程
2020/06/08 Python
极简鞋类,赤脚的感觉:Lems Shoes
2019/08/06 全球购物
声明struct x1 { . . . }; 和typedef struct { . . . }x2;有什么不同
2012/06/02 面试题
Servlet的生命周期
2013/08/25 面试题
Delphi笔试题
2016/11/14 面试题
向领导表决心的话
2014/03/11 职场文书
2014年个人年终总结
2015/03/09 职场文书
2015年办公室文员工作总结
2015/04/24 职场文书
百家讲坛观后感
2015/06/12 职场文书
2016年幼儿园庆六一开幕词
2016/03/04 职场文书
教您:房贷工资收入证明应该怎么写?
2019/08/19 职场文书
【海涛教你打DOTA】剑圣第一人称视角解说
2022/04/01 DOTA