javascript实现贪吃蛇经典游戏


Posted in Javascript onApril 10, 2020

js面向对象编程之贪吃蛇,供大家参考,具体内容如下

首先:面向对象编程,我们要找到项目中具体的对象,此处为(食物(food),蛇(snake),游戏本身(game))也可不把游戏本身作为对象,逻辑体现出来即可。

接着分析每个对象的具体的属性及方法:
1)food 对象:属性有:位置,大小,颜色;方法有:渲染在页面,随机不同位置生成;
2)snake对象:属性有:位置,大小,总节数(计分方便),颜色;方法有:渲染在页面,移动(移动过程中判断其它)。
3)game对象:游戏逻辑的编写;

ok 开敲:

1)简单的静态页面编写(地图)

(1)html

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <link rel="stylesheet" href="css/index.css" >
 <script src="js/food.js"></script>
 <script src="js/snake.js"></script>
 <script src="js/game.js"></script>
 <script src="js/main.js"></script>
 <title>贪吃蛇</title>
</head>
<body>
 <div class="map"></div>
</body>
</html>

(2)css(如果用边框来作为限制的边界,那么box-sizing属性是必不可少的(以免食物和蛇头坐标之间存在误差))

* {
 margin: 0;
 padding: 0;
}

.map {
 position: relative;
 height: 600px;
 width: 800px;
 border: 1px solid #333;
 margin: 0 auto;
 /* 盒子模型去除边框 */
 box-sizing: border-box;
}

2)food对象编写(细节处含注释)

//cwen加载页面所有元素
window.addEventListener('load', function() {

 //cwen自调用函数,开启一个新的作用域,避免命名冲突
 (function() {

 //cwen定义全局变量
 //实物数组
 var elements = [];
 //cwen实物
 function Food(options) {
  options = options || {};
  this.x = options.x || 0;
  this.y = options.y || 0;
  this.width = options.width || 20;
  this.height = options.height || 20;
  this.color = options.color || 'yellow';
 }


 //cwen随机数函数
 function getRandom(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
 }
 //cwen渲染
 Food.prototype.render = function(map) {
  //删除之前的食物
  remove();
  //todo动态创建div实物
  var div = document.createElement('div');
  map.appendChild(div);
  //把div添加给数组
  elements.push(div);
  //todo随机设置x,y的值(实物的位置)-----在map中生成随机位置
  // ! 值 = Math.floor(Math.random() * 可能值得总数 + 第一个可能的值)
  this.x = getRandom(0, map.offsetWidth / this.width - 1) * this.width;
  this.y = getRandom(0, map.offsetHeight / this.height - 1) * this.height;
  div.style.position = 'absolute';
  div.style.left = this.x + 'px';
  div.style.top = this.y + 'px';
  div.style.width = this.width + 'px';
  div.style.height = this.height + 'px';
  div.style.backgroundColor = this.color;
 }

 function remove() {
  //为了删除干净,从索引最大的开始循环删除
  for (var i = elements.length - 1; i >= 0; i--) {
  //删除遍历到的div
  elements[i].parentNode.removeChild(elements[i]);
  //删除数组中的元素1)第几个开始,2)要删除个数
  elements.splice(i, 1);
  }
 }

 //把Food开放出去
 window.Food = Food;
 })()
 
 //cwen测试
 // var map = document.querySelector('.map');
 // var options = { x: 20, y: 20, width: 30, height: 30, color: 'green' };
 // //todo不传值默认为自定义food
 // var food = new Food();
 // food.render(map);
})

3)snake对象编写()

window.addEventListener('load', function() {
 (function() {
 //记录蛇的每一节
 var elements = [];
 //cwen立即执行函数,开启新的作用于,避免命名冲突
 function Snake(options) {
  options = options || {};
  //对象(蛇)每节的大小
  this.width = options.width || 20;
  this.height = options.height || 20;
  //cwen蛇的总节数(计分)
  this.mark = options.mark || 0;
  //对象的移动方向
  this.direction = options.direction || 'right';
  //对象的身体(蛇节)
  this.kont = [{ x: 3, y: 2, color: 'red' }, { x: 2, y: 2, color: 'black' }, { x: 1, y: 2, color: 'black' }];
 }

 //cwen渲染对象
 Snake.prototype.render = function(map) {
  //移除之前的蛇
  remove();
  //循环输出对象的身体(蛇节)
  for (var i = 0, len = this.kont.length; i < len; i++) {
  var obj = this.kont[i];
  var div = document.createElement('div');
  map.appendChild(div);
  //将蛇节添加入数组
  elements.push(div);
  //添加样式
  div.style.position = 'absolute';
  div.style.width = this.width + 'px';
  div.style.height = this.height + 'px';
  div.style.left = obj.x * this.width + 'px';
  div.style.top = obj.y * this.height + 'px';
  div.style.backgroundColor = obj.color;
  }
 }

 //cwen控制蛇移动的方法
 //todo传参food,map 在game中调用move方法也要传入相应参数
 Snake.prototype.move = function(food, map) {
  //控制蛇节的移动(当前蛇节到下一个蛇节的位置)
  for (var i = this.kont.length - 1; i > 0; i--) {
  this.kont[i].x = this.kont[i - 1].x;
  this.kont[i].y = this.kont[i - 1].y;
  }

  //判断并控制蛇头移动,判断蛇头移动方向
  var head = this.kont[0];
  switch (this.direction) {
  case 'right':
   head.x += 1;
   break;
  case 'left':
   head.x -= 1;
   break;
  case 'top':
   head.y -= 1;
   break;
  case 'bottom':
   head.y += 1;
   break;
  }


  //蛇头碰到食物时处理
  // cwen判断蛇头是否和食物坐标重合
  var headX = head.x * this.width;
  var headY = head.y * this.height;
  if (headX == food.x && headY == food.y) {
  //1,增加蛇节(找到最后一根蛇节,然后添加给创建的蛇数组)
  var last = this.kont[this.kont.length - 1];
  this.kont.push({ x: last.x, y: last.y, color: last.color });
  //cwen求出蛇节的总个数(计分)
  var mark = this.mark++;
  //2,重新渲染食物
  food.render(map);
  }
 }


 //删除之前的蛇
 function remove() {
  for (var i = elements.length - 1; i >= 0; i--) {
  elements[i].parentNode.removeChild(elements[i]);
  elements.splice(i, 1);
  }
 }

 //把Snake构造函数暴露出去
 window.Snake = Snake;
 })()
 //测试
 // var map = document.querySelector('.map');
 // var snake = new Snake();
 // snake.render(map);
})

4)game对象编写,其中一个为无敌版(含细节注释)

window.addEventListener('load', function() {
 (function() {
 //改变计时器内this指向
 var that;

 function Game(map) {
  // var options = { x: 20, y: 20, width: 30, height: 30, color: 'green' };
  this.food = new Food();
  this.snake = new Snake();
  this.map = map;
  that = this;
 }
 //cwen渲染
 Game.prototype.start = function() {
  // 1.把食物和蛇渲染到页面
  this.food.render(this.map);
  this.snake.render(this.map);
  // 2.游戏逻辑编写
  //让蛇动起来
  //判断地图边界
  // runSnake();
  //todo判断玩法(两种模式,原理一样)
  goInput();
  //通过键盘控制蛇头方向
  //! keydown();
  //蛇头碰到食物时处理
  //在snake.js中判断
 }

 function goInput() {
  var it = prompt('try:\n 经典玩法请按1\n 无敌玩法请输入(博主最帅)\n')
  if (it == 1) {
  runSnake();
  keydown();
  } else if (it == '博主最帅') {
  runSnake1();
  keydown1();
  } else {
  alert('you input could not be found!!!');
  goInput();
  }
 }


 //让蛇动起来
 function runSnake() {
  var timeId = setInterval(function() {
  // var a = mark;
  that.snake.move(that.food, that.map);
  that.snake.render(that.map);

  //判断地图边界
  var maxX = (that.map.offsetWidth) / that.snake.width;
  var maxY = (that.map.offsetHeight) / that.snake.height;
  var headX = that.snake.kont[0].x;
  var headY = that.snake.kont[0].y;
  if (headX < 0 || headX >= maxX) {
   alert('Game Over ' + '得分为 ' + that.snake.mark);
   clearInterval(timeId);
  } else if (headY < 0 || headY >= maxY) {
   alert('Game Over ' + '成绩为 ' + that.snake.mark);
   clearInterval(timeId);
  }
  }, 150)
 }


 //无敌版本蛇运动
 function runSnake1() {
  var timeId1 = setInterval(function() {
  that.snake.move(that.food, that.map);
  that.snake.render(that.map);

  //判断地图边界
  var maxX = (that.map.offsetWidth - that.snake.width) / that.snake.width;
  var maxY = (that.map.offsetHeight - that.snake.height) / that.snake.height;
  var headX = that.snake.kont[0].x;
  var headY = that.snake.kont[0].y;

  if (headX < 0) {
   that.snake.kont[0].x = (that.map.offsetWidth - that.snake.width) / that.snake.width;
  } else if (headX > maxX) {
   that.snake.kont[0].x = 0;
  } else if (headY < 0) {
   that.snake.kont[0].y = (that.map.offsetHeight - that.snake.height) / that.snake.height;
  } else if (headY > maxY) {
   that.snake.kont[0].y = 0;
  }
  }, 50)
 }



 //通过键盘控制蛇头方向
 function keydown() {
  document.addEventListener('keydown', function(e) {
  //通过事件对象判断按了哪个键 37left,38top,39right,40bottom
  // console.log(e.keyCode);
  //其在走的同时按下反方向无用
  if (e.keyCode == 37 && that.snake.direction != 'right') {
   that.snake.direction = 'left';
  } else if (e.keyCode == 38 && that.snake.direction != 'bottom') {
   that.snake.direction = 'top';
  } else if (e.keyCode == 39 && that.snake.direction != 'left') {
   that.snake.direction = 'right';
  } else if (e.keyCode == 40 && that.snake.direction != 'top') {
   that.snake.direction = 'bottom';
  }
  });
 }


 function keydown1() {
  document.addEventListener('keydown', function(e) {
  //通过事件对象判断按了哪个键 37left,38top,39right,40bottom
  // console.log(e.keyCode);
  //无敌版本四面八方任你行
  if (e.keyCode == 37) {
   that.snake.direction = 'left';
  } else if (e.keyCode == 38) {
   that.snake.direction = 'top';
  } else if (e.keyCode == 39) {
   that.snake.direction = 'right';
  } else if (e.keyCode == 40) {
   that.snake.direction = 'bottom';
  }
  });
 }


 //把Game开放
 window.Game = Game;
 })()
})

5)main开启游戏

window.addEventListener('load', function() {
 (function(window, undefind) {
 //测试
 var map = document.querySelector('.map');
 var game = new Game(map);
 game.start();

 })(window, undefined)
})

last but not least
*建议把所有js文件写在同一个js文件中,可以大大提高加载速度。注意在每个立即执行函数前加上‘ ;',以免出错。

小编还为大家准备了精彩的专题:javascript经典小游戏汇总

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
ECMAScript 5严格模式(Strict Mode)介绍
Mar 02 Javascript
jQuery多级手风琴菜单实例讲解
Oct 22 Javascript
Extjs实现下拉菜单效果
Apr 01 Javascript
基于JavaScript实现点击页面任何位置返回
Aug 31 Javascript
javascript显示系统当前时间代码
Dec 29 Javascript
微信小程序 出现47001 data format error原因解决办法
Mar 10 Javascript
详解webpack与SPA实践之开发环境搭建
Dec 18 Javascript
vue 配置多页面应用的示例代码
Oct 22 Javascript
jQuery中使用validate插件校验表单功能
May 24 jQuery
JS快速实现简单计算器
Apr 08 Javascript
解决vue里a标签值解析变量,跳转页面,前面加默认域名端口的问题
Jul 22 Javascript
JS变量提升及函数提升实例解析
Sep 03 Javascript
javascript设计模式 ? 原型模式原理与应用实例分析
Apr 10 #Javascript
Quasar Input:type=&quot;number&quot; 去掉上下小箭头 实现加减按钮样式功能
Apr 09 #Javascript
vue中的过滤器及其时间格式化问题
Apr 09 #Javascript
微信小程序保存图片到相册权限设置
Apr 09 #Javascript
微信小程序仿通讯录功能
Apr 09 #Javascript
vue cli4下环境变量和模式示例详解
Apr 09 #Javascript
微信小程序实现组件顶端固定或底端固定效果(不随滚动而滚动)
Apr 09 #Javascript
You might like
用PHP和ACCESS写聊天室(二)
2006/10/09 PHP
VIM中设置php自动缩进为4个空格的方法详解
2013/06/14 PHP
php去掉URL网址中带有PHPSESSID的配置方法
2014/07/08 PHP
Yii中CGridView关联表搜索排序方法实例详解
2014/12/03 PHP
用PHP写的一个冒泡排序法的函数简单实例
2016/05/26 PHP
PHP的mysqli_stat()函数讲解
2019/01/23 PHP
Jquery.LazyLoad.js修正版下载,实现图片延迟加载插件
2011/03/12 Javascript
JavaScript下通过的XMLHttpRequest发送请求的代码
2011/06/28 Javascript
动态获取复选框checkbox选中个数的jquery代码
2013/06/25 Javascript
node.js中的querystring.parse方法使用说明
2014/12/10 Javascript
Jquery实现鼠标移动放大图片功能实例
2015/03/25 Javascript
JavaScript重定向URL参数的两种方法小结
2016/10/19 Javascript
详解AngularJS用Interceptors来统一处理HTTP请求和响应
2017/06/08 Javascript
bootstrap3-dialog-master模态框使用详解
2017/08/22 Javascript
vue.js获得当前元素的文字信息方法
2018/03/09 Javascript
Vue组件中prop属性使用说明实例代码详解
2018/05/31 Javascript
VUE中v-on:click事件中获取当前dom元素的代码
2018/08/22 Javascript
在vue中使用express-mock搭建mock服务的方法
2018/11/07 Javascript
详解keep-alive + vuex 让缓存的页面灵活起来
2019/04/19 Javascript
监控Nodejs的性能实例代码
2019/07/02 NodeJs
redux处理异步action解决方案
2020/03/22 Javascript
javascript实现前端成语点击验证
2020/06/24 Javascript
[01:02:48]2018DOTA2亚洲邀请赛 4.1 小组赛 A组 LGD vs OG
2018/04/02 DOTA
python的Template使用指南
2014/09/11 Python
以911新闻为例演示Python实现数据可视化的教程
2015/04/23 Python
Python实现的Excel文件读写类
2015/07/30 Python
python 递归遍历文件夹,并打印满足条件的文件路径实例
2017/08/30 Python
Django高级编程之自定义Field实现多语言
2019/07/02 Python
Python数据类型之列表和元组的方法实例详解
2019/07/08 Python
windows 10 设定计划任务自动执行 python 脚本的方法
2019/09/11 Python
基于PyTorch的permute和reshape/view的区别介绍
2020/06/18 Python
Python自动化之UnitTest框架实战记录
2020/09/08 Python
python3中for循环踩过的坑记录
2020/12/14 Python
在weblogic中发布ejb需涉及到哪些配置文件
2012/01/17 面试题
中英双版中文教师求职信
2013/10/27 职场文书
观看《筑梦中国》纪录片心得体会
2016/01/18 职场文书