基于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 相关文章推荐
超清晰的document对象详解
Feb 27 Javascript
JXTree对象,读取外部xml文件数据,生成树的函数
Apr 02 Javascript
jqgrid 编辑添加功能详细解析
Nov 08 Javascript
仿百度联盟对联广告实现代码
Aug 30 Javascript
javascript中Array数组的迭代方法实例分析
Feb 04 Javascript
JavaScript获得页面base标签中url的方法
Apr 03 Javascript
js实现添加可信站点、修改activex安全设置,禁用弹出窗口阻止程序
Aug 17 Javascript
Angularjs中使用指令绑定点击事件的方法
Mar 30 Javascript
JS实现网页抢购功能(触发,终止脚本)
Nov 27 Javascript
vue项目tween方法实现返回顶部的示例代码
Mar 02 Javascript
浅谈Three.js截图并下载的大坑
Nov 01 Javascript
基于javascript实现贪吃蛇经典小游戏
Apr 10 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
JavaScript 事件的一些重要说明
2009/10/25 Javascript
用js写了一个类似php的print_r输出换行功能
2013/02/18 Javascript
JS判断数组中是否有重复值得三种实用方法
2013/08/16 Javascript
js浮点数精确计算(加、减、乘、除)
2013/12/26 Javascript
JavaScript中的toLocaleLowerCase()方法使用详解
2015/06/06 Javascript
js中对函数设置默认参数值的3种方法
2015/10/23 Javascript
JavaScript观察者模式(经典)
2015/12/09 Javascript
JS实现页面进入和返回定位到具体位置
2016/12/08 Javascript
Mongoose学习全面理解(推荐)
2017/01/21 Javascript
canvas实现钟表效果
2017/02/13 Javascript
关于Bootstrap按钮组件消除黄框的方法
2017/05/19 Javascript
JavaScript 获取元素在父节点中的下标(推荐)
2017/06/28 Javascript
vue 将页面公用的头部组件化的方法
2017/12/18 Javascript
react native 文字轮播的实现示例
2018/07/27 Javascript
详解node字体压缩插件font-spider的用法
2018/09/28 Javascript
vue cli3.0 引入eslint 结合vscode使用
2019/05/27 Javascript
在vue中把含有html标签转为html渲染页面的实例
2019/10/28 Javascript
JS运算符优先级与表达式示例详解
2020/09/04 Javascript
[43:32]Winstrike vs VGJ.S 2018国际邀请赛淘汰赛BO3 第一场 8.23
2018/08/24 DOTA
Python Deque 模块使用详解
2014/07/04 Python
python获取程序执行文件路径的方法(推荐)
2018/04/26 Python
PyQt5 pyqt多线程操作入门
2018/05/05 Python
Python中捕获键盘的方式详解
2019/03/28 Python
Flask框架模板继承实现方法分析
2019/07/31 Python
一行python实现树形结构的方法
2019/08/09 Python
wxPython电子表格功能wx.grid实例教程
2019/11/19 Python
django配置app中的静态文件步骤
2020/03/27 Python
python操作redis数据库的三种方法
2020/09/10 Python
Python包资源下载路径报404解决方案
2020/11/05 Python
荷兰照明、灯具和配件网上商店:dmlights
2019/08/25 全球购物
财务会计毕业生个人求职信
2014/02/03 职场文书
节能减耗标语
2014/06/21 职场文书
大学生求职信例文
2014/06/29 职场文书
庆祝教师节演讲稿
2014/09/03 职场文书
公安交警中队队长个人对照检查材料思想汇报
2014/10/05 职场文书
2014年林业工作总结
2014/12/05 职场文书