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 相关文章推荐
一页面多XMLHttpRequest对象
Jan 22 Javascript
用JS实现的一个include函数
Jul 21 Javascript
js 图片等比例缩放代码
May 13 Javascript
xml转json的js代码
Aug 28 Javascript
AngularJS表单编辑提交功能实例
Feb 13 Javascript
JS获取Table中td值的方法
Mar 19 Javascript
JavaScript实现点击按钮直接打印
Jan 06 Javascript
vue+webpack实现异步组件加载的方法
Feb 03 Javascript
Angularjs之ngModel中的值验证绑定方法
Sep 13 Javascript
vue输入节流,避免实时请求接口的实例代码
Oct 30 Javascript
浅谈vue中使用编辑器vue-quill-editor踩过的坑
Aug 03 Javascript
jQuery实现手风琴特效
Jan 11 jQuery
小程序绑定用户方案优化小结
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
PHP和JAVA中的重载(overload)和覆盖(override) 介绍
2012/03/01 PHP
PHP读取大文件的几种方法介绍
2016/10/27 PHP
使用PHP连接多种数据库的实现代码(mysql,access,sqlserver,Oracle)
2016/12/21 PHP
php mysql_list_dbs()函数用法示例
2017/03/29 PHP
PHP封装类似thinkphp连贯操作数据库Db类与简单应用示例
2019/05/08 PHP
PHP实现带进度条的Ajax文件上传功能示例
2019/07/02 PHP
jquery 得到当前页面高度和宽度的两个函数
2010/02/21 Javascript
Javascript 实用小技巧
2010/04/07 Javascript
javascript实现点击商品列表checkbox实时统计金额的方法
2015/05/15 Javascript
js中使用使用原型(prototype)定义方法的好处详解
2016/07/04 Javascript
解析JavaScript实现DDoS攻击原理与保护措施
2016/12/26 Javascript
JavaScript实现自动跳转文本功能
2017/05/25 Javascript
Vue2 配置 Axios api 接口调用文件的方法
2017/11/13 Javascript
jQuery实现简单的下拉菜单导航功能示例
2017/12/07 jQuery
微信小程序自定义底部弹出框
2020/11/16 Javascript
ES6中let、const的区别及变量的解构赋值操作方法实例分析
2019/10/15 Javascript
js实现无缝轮播图特效
2020/05/09 Javascript
JS script脚本中async和defer区别详解
2020/06/24 Javascript
国内常用的js类库大全(CDN公共库)
2020/06/24 Javascript
基于p5.js 2D图像接口的扩展(交互实现)
2020/11/30 Javascript
[52:57]2014 DOTA2国际邀请赛中国区预选赛 LGD-CDEC VS HGT
2014/05/21 DOTA
Python xlrd读取excel日期类型的2种方法
2015/04/28 Python
python中enumerate函数用法实例分析
2015/05/20 Python
Python函数中*args和**kwargs来传递变长参数的用法
2016/01/26 Python
Python random模块用法解析及简单示例
2017/12/18 Python
浅谈pytorch卷积核大小的设置对全连接神经元的影响
2020/01/10 Python
美国高端寝具品牌:Coyuchi
2017/02/08 全球购物
俄罗斯EPL钻石珠宝店:ЭПЛ
2019/10/22 全球购物
中间件分为哪几类
2016/09/18 面试题
外贸销售员求职的自我评价
2013/11/23 职场文书
优秀毕业生自我鉴定
2014/02/11 职场文书
办公室主任职责范本
2014/03/07 职场文书
2015年公务员转正工作总结
2015/04/24 职场文书
地雷战观后感
2015/06/09 职场文书
导游词之山海关
2019/12/10 职场文书
导游词之介休绵山
2019/12/31 职场文书