基于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 相关文章推荐
jQuery .tmpl() 用法示例介绍
Aug 21 Javascript
JavaScript中检查对象property的存在性方法介绍
Dec 30 Javascript
js对象的复制继承实例
Jan 10 Javascript
使用JavaScript和CSS实现文本隔行换色的方法
Nov 04 Javascript
JavaScript基本语法学习教程
Jan 14 Javascript
简述JavaScript提交表单的方式 (Using JavaScript Submit Form)
Mar 18 Javascript
jQuery animate easing使用方法图文详解
Jun 17 Javascript
任意Json转成无序列表的方法示例
Dec 09 Javascript
vue mounted 调用两次的完美解决办法
Oct 29 Javascript
Angular Excel 导入与导出的实现代码
Apr 17 Javascript
Angular封装表单控件及思想总结
Dec 11 Javascript
Vue-cli3生成的Vue项目加载Mxgraph方法示例
May 31 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
星际争霸 Starcraft 秘技补丁
2020/03/14 星际争霸
快速开发一个PHP扩展图文教程
2008/12/12 PHP
Cakephp 执行主要流程
2010/03/24 PHP
可拖动窗口,附带鼠标控制渐变透明,开启关闭功能
2006/06/26 Javascript
基于jquery的下拉框改变动态添加和删除表格实现代码
2020/09/12 Javascript
关于js datetime的那点事
2011/11/15 Javascript
使用js操作cookie的一点小收获分享
2013/09/03 Javascript
跟我学Nodejs(一)--- Node.js简介及安装开发环境
2014/05/20 NodeJs
jQuery中removeProp()方法用法实例
2015/01/05 Javascript
jquery插件star-rating.js实现星级评分特效
2015/04/15 Javascript
jQuery页面刷新(局部、全部)问题分析
2016/01/09 Javascript
js表单登陆验证示例
2016/10/19 Javascript
JS如何设置iOS中微信浏览器的title
2016/11/22 Javascript
js获取元素下的第一级子元素的方法(推荐)
2017/03/05 Javascript
Javacript中自定义的map.js  的方法
2017/11/26 Javascript
浅谈webpack组织模块的原理
2018/03/10 Javascript
Vue利用canvas实现移动端手写板的方法
2018/05/03 Javascript
vue 插件的方法代码详解
2019/06/06 Javascript
通过代码实例展示Python中列表生成式的用法
2015/03/31 Python
python集合类型用法分析
2015/04/08 Python
python使用分治法实现求解最大值的方法
2015/05/12 Python
在python3.5中使用OpenCV的实例讲解
2018/04/02 Python
python游戏地图最短路径求解
2019/01/16 Python
Python面向对象之Web静态服务器
2019/09/03 Python
Jupyter Notebook输出矢量图实例
2020/04/14 Python
Python flask路由间传递变量实例详解
2020/06/03 Python
加拿大花店:1800Flowers.ca
2016/11/16 全球购物
全球性的众包图形设计市场:DesignCrowd
2021/02/02 全球购物
试述DBMS的主要功能
2016/11/13 面试题
Java程序员综合测试题
2014/04/25 面试题
外贸采购员求职的自我评价
2013/11/26 职场文书
大学四年规划书范文
2013/12/27 职场文书
经营理念口号
2014/06/21 职场文书
幼儿园秋季开学寄语
2014/08/02 职场文书
创先争优公开承诺书
2014/08/30 职场文书
win11开机发生死循环重启怎么办?win11开机发生死循环重启解决方法
2022/08/05 数码科技