基于JavaScript实现贪吃蛇游戏


Posted in Javascript onMarch 16, 2020

本文实例为大家分享了JavaScript实现贪吃蛇游戏的具体代码,供大家参考,具体内容如下

1.结构

创建一个盒子box作为蛇的身体,当前盒子中只有一个子元素,代表此时蛇的长度为1.
在创建一个盒子food作为贪吃蛇的食物。

<div id="box">
  <div></div>
</div>
<div id="food"></div>

2.CSS

设置蛇和食物的样式,这里注意蛇和食物都是绝对定位。

<style>
 *{
  padding: 0px;
  margin: 0px;
 }
 #box div{
  width: 30px;
  height: 30px;
  box-sizing: border-box;
  background: green;
  border: 1px solid black;
  position: absolute;
 }
 #food{
  width: 30px;
  height: 30px;
  background: brown;
  position: absolute;
 }
 </style>

3.脚本

获取蛇的身体和每一个子元素

var box = document.getElementById("box");
var boxs = document.getElementById("box").children;

定义蛇头的位置

var snackX = 0;
var snackY = 0;

获取屏幕宽度和高度,以此来设定墙的边界,以限制蛇的移动范围。

var cw = document.documentElement.clientWidth;
 var ch = document.documentElement.clientHeight;
 var minsnackX = 0;
 var maxsnackX = Math.floor(cw / boxs[0].offsetWidth)*boxs[0].offsetWidth;
 var minsnackY = 0;
 var maxsnackY = Math.floor(ch / boxs[0].offsetHeight)*boxs[0].offsetHeight;

定义初始的移动方向。

var turn = "right";

获取食物元素,并设置食物的位置坐标。

var foodele = document.getElementById("food");
 var foodX,foodY;

蛇的初始化

for(var i = 0; i <6 ; i++){
  box.appendChild(boxs[0].cloneNode(true));
 }

刷新食物

function food(){
 //此处的坐标要先获取页面最大支持的蛇身体的块数,然后在块数中随机,然后乘以块数的大小,
 //因为蛇的移动每一步都是固定的,想要判定食物和蛇头重合就必须坐标是整块的倍数。
  foodX = parseInt( Math.random()*Math.floor(cw / boxs[0].offsetWidth))*boxs[0].offsetWidth;
  foodY = parseInt( Math.random()*Math.floor(ch / boxs[0].offsetHeight))*boxs[0].offsetHeight;
  //判定当食物的产生位置和蛇的任何一个位置重合时就重新生成食物。
  for(var i = 0;i<boxs.length;i++){
   if(foodX + "px" === boxs[i].style.left && foodY + "px" === boxs[i].style.top){
    food();
   }
  }
  foodele.style.left = foodX + "px";
  foodele.style.top = foodY + "px";
 }

调用food()方法 生成第一个食物

food();

设置定时器 每次执行一次蛇的运行方法

var timer = setInterval(function(){
  snackMOve();
 },150)

封装一个蛇的运动方法

//移动和判定边界
 function snackMOve(){
//此处为判定方向 根据判定的方向,向改方向前进一个方块
  switch(turn){
   case "right":snackX +=30;break;
   case "left":snackX -=30;break;
   case "bottom":snackY +=30;break;
   case "top":snackY -=30;break;
  }
  //如果蛇越过了墙就从另一端出现
  if(snackX > maxsnackX){
   snackX = 0;
  }
  if(snackX < minsnackX){
   snackX = maxsnackX;
  }
  if(snackY > maxsnackY){
   snackY = 0;
  } 
  if(snackY < minsnackY){
   snackY = maxsnackY;
  }
  //从最后一个开始,每个元素跟随上一个元素的位置
  for(var i = boxs.length-1; i >0 ; i--){
   boxs[i].style.left = boxs[i-1].style.left;
   boxs[i].style.top = boxs[i-1].style.top ;
  }
  //第一个也就是蛇头的位置,永远是根据方向获取的位置
  boxs[0].style.left = snackX + "px";
  boxs[0].style.top = snackY + "px" ;


  //判定吃到食物 就长大和刷新
  //当蛇头位置移动之后与食物重合 那么刷新食物,并且在蛇的身体中插入一个克隆的元素,相当于长度+1
  if(snackX === foodX && snackY === foodY){
   food();
   box.appendChild(boxs[0].cloneNode(true));
  }else{
  //判定撞死 
  //当蛇头与身体中的任何一个元素重合,那么判定结束游戏,停止定时器
   for(var i = 1;i<boxs.length;i++){
    if(snackX + "px" === boxs[i].style.left && snackY + "px" === boxs[i].style.top){
     clearInterval(timer);
     alert("失败");
    }
   }
  }
 }

蛇的运动方向

document.onkeydown = function(eve){
 var e = eve||event;
 var keyCode = e.keyCode||e.which;
 switch(keyCode){
  case 37:if(turn === "right"){break;}turn = "left";break;
  case 38:if(turn === "bottom"){break;}turn = "top";break;
  case 39:if(turn === "left"){break;}turn = "right";break;
  case 40:if(turn === "top"){break;}turn = "bottom";break;
 }  
}

全部代码

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <meta http-equiv="X-UA-Compatible" content="ie=edge">
 <title>Document</title>
 <style>
 *{
  padding: 0px;
  margin: 0px;
 }
 #box div{
  width: 30px;
  height: 30px;
  box-sizing: border-box;
  background: green;
  border: 1px solid black;
  position: absolute;
 }
 #food{
  width: 30px;
  height: 30px;
  background: brown;
  position: absolute;
 }
 </style>
</head>
<body>
 <div id="box">
  <div></div>
 </div>
 <div id="food"></div>
 <script>
  var box = document.getElementById("box");
  var boxs = document.getElementById("box").children;
  var snackX = 0;
  var snackY = 0;
  var cw = document.documentElement.clientWidth;
  var ch = document.documentElement.clientHeight;
  var minsnackX = 0;
  var maxsnackX = Math.floor(cw / boxs[0].offsetWidth)*boxs[0].offsetWidth;
  var minsnackY = 0;
  var maxsnackY = Math.floor(ch / boxs[0].offsetHeight)*boxs[0].offsetHeight;
  var turn = "right";
  var foodele = document.getElementById("food");
  var foodX,foodY;

  for(var i = 0; i <6 ; i++){
   box.appendChild(boxs[0].cloneNode(true));
  }


  //随机食物
  function food(){
   foodX = parseInt( Math.random()*Math.floor(cw / boxs[0].offsetWidth))*boxs[0].offsetWidth;
   foodY = parseInt( Math.random()*Math.floor(ch / boxs[0].offsetHeight))*boxs[0].offsetHeight;
   for(var i = 0;i<boxs.length;i++){
    if(foodX + "px" === boxs[i].style.left && foodY + "px" === boxs[i].style.top){
     food();
    }
   }
   foodele.style.left = foodX + "px";
   foodele.style.top = foodY + "px";
  }
  food();

  //设置定时器 移动
  var timer = setInterval(function(){
   snackMOve();
  },150)


  //移动和判定边界
  function snackMOve(){
   switch(turn){
    case "right":snackX +=30;break;
    case "left":snackX -=30;break;
    case "bottom":snackY +=30;break;
    case "top":snackY -=30;break;
   }
   //根据边界归零
   if(snackX > maxsnackX){
    snackX = 0;
   }
   if(snackX < minsnackX){
    snackX = maxsnackX;
   }
   if(snackY > maxsnackY){
    snackY = 0;
   } 
   if(snackY < minsnackY){
    snackY = maxsnackY;
   }
   for(var i = boxs.length-1; i >0 ; i--){
    boxs[i].style.left = boxs[i-1].style.left;
    boxs[i].style.top = boxs[i-1].style.top ;
   }
   boxs[0].style.left = snackX + "px";
   boxs[0].style.top = snackY + "px" ;


   //判定吃到食物 就长大和刷新
   if(snackX === foodX && snackY === foodY){
    food();
    box.appendChild(boxs[0].cloneNode(true));
   }else{
   //判定撞死 暂停计时器 刷新
    for(var i = 1;i<boxs.length;i++){
     // console.log(boxs[i].style.left);
     if(snackX + "px" === boxs[i].style.left && snackY + "px" === boxs[i].style.top){
      clearInterval(timer);
      alert("失败");
      // console.log(1)
     }
    }
   }
  }


  //方向
  document.onkeydown = function(eve){
   var e = eve||event;
   var keyCode = e.keyCode||e.which;
   switch(keyCode){
    case 37:if(turn === "right"){break;}turn = "left";break;
    case 38:if(turn === "bottom"){break;}turn = "top";break;
    case 39:if(turn === "left"){break;}turn = "right";break;
    case 40:if(turn === "top"){break;}turn = "bottom";break;
   }  
  }
 </script>
</body>
</html>

总结

贪吃蛇的思路主要是有以下几个部分

1.食物的随机出现(不能随机在蛇身上)
2.定时器控制蛇的移动
3.墙的判定
4.蛇的运动逻辑
5.运动方向的判定
6.吃到食物的判定
7.蛇头与身体的判定(即游戏结束的判定)

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

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

Javascript 相关文章推荐
JavaScript入门教程(5) js Screen屏幕对象
Jan 31 Javascript
小试JQuery的AutoComplete插件
May 04 Javascript
yepnope.js使用详解及示例分享
Jun 23 Javascript
js 通过cookie实现刷新不变化树形菜单
Oct 30 Javascript
老生常谈combobox和combotree模糊查询
Apr 17 Javascript
React数据传递之组件内部通信的方法
Dec 31 Javascript
5 种JavaScript编码规范
Jan 30 Javascript
命令行批量截图Node脚本示例代码
Jan 25 Javascript
详解webpack 最简打包结果分析
Feb 20 Javascript
全面分析JavaScript 继承
May 30 Javascript
后台使用freeMarker和前端使用vue的方法及遇到的问题
Jun 13 Javascript
js全屏事件fullscreenchange 实现全屏、退出全屏操作
Sep 17 Javascript
原生js实现的金山打字小游戏(实例代码详解)
Mar 16 #Javascript
JavaScript实现拖拽效果
Mar 16 #Javascript
js实现点赞效果
Mar 16 #Javascript
Javascript Web Worker使用过程解析
Mar 16 #Javascript
Javascript ParentNode和ChildNode接口原理解析
Mar 16 #Javascript
JS手写一个自定义Promise操作示例
Mar 16 #Javascript
JS函数参数的传递与同名参数实例分析
Mar 16 #Javascript
You might like
PHP 配置open_basedir 让各虚拟站点独立运行
2009/11/12 PHP
php 静态变量与自定义常量的使用方法
2010/01/26 PHP
PHP中的流(streams)浅析
2015/07/02 PHP
php实现微信公众号无限群发
2015/10/11 PHP
CodeIgniter框架数据库基本操作示例
2018/05/24 PHP
php获取是星期几的的一些常用姿势
2019/12/15 PHP
javascript cookies操作集合
2010/04/12 Javascript
jquery 3D球状导航的文章分类
2010/07/06 Javascript
jQuery学习笔记之jQuery的事件
2010/12/22 Javascript
jQuery子属性过滤选择器用法分析
2015/02/10 Javascript
JS模拟实现Select效果代码
2015/09/24 Javascript
jquery实现左右无缝轮播图
2020/07/31 Javascript
jQuery插件Validation快速完成表单验证的方式
2016/07/28 Javascript
AngularJS基础 ng-model 指令详解及示例代码
2016/08/02 Javascript
Node.js  事件循环详解及实例
2017/08/06 Javascript
jQuery Datatable 多个查询条件自定义提交事件(推荐)
2017/08/24 jQuery
浅谈vue的props,data,computed变化对组件更新的影响
2018/01/16 Javascript
vue使用v-if v-show页面闪烁,div闪现的解决方法
2018/10/12 Javascript
从0到1构建vueSSR项目之node以及vue-cli3的配置
2019/03/07 Javascript
thinkjs微信中控之微信鉴权登陆的实现代码
2019/08/08 Javascript
解决Echarts2竖直datazoom滑动后显示数据不全的问题
2020/07/20 Javascript
Python简单计算文件夹大小的方法
2015/07/14 Python
Python使用jsonpath-rw模块处理Json对象操作示例
2018/07/31 Python
Python3.5实现的三级菜单功能示例
2019/03/25 Python
python传到前端的数据,双引号被转义的问题
2020/04/03 Python
Tensorflow中的图(tf.Graph)和会话(tf.Session)的实现
2020/04/22 Python
HTML5 语音搜索(淘宝店语音搜素)
2013/01/03 HTML / CSS
项目副经理岗位职责
2013/12/30 职场文书
生日礼品店创业计划书范文
2014/03/21 职场文书
关于保护环境的建议书
2014/05/13 职场文书
云冈石窟导游词
2015/02/04 职场文书
法律进社区活动总结
2015/05/07 职场文书
小兵张嘎观后感
2015/06/03 职场文书
Python实现byte转integer
2021/06/03 Python
高性能跳频抗干扰宽带自组网电台
2022/02/18 无线电
pytest实现多进程与多线程运行超好用的插件
2022/07/15 Python