js实现简单贪吃蛇游戏


Posted in Javascript onMay 15, 2020

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

上下左右键控制方向使贪吃蛇吃葡萄
吃5个葡萄,游戏结束时左上角为总得分。

运行结果:

js实现简单贪吃蛇游戏

界面和css代码这里就不加赘述了,主要贴js代码(加了注释):

var config = {
 width: 20, //一个格子的宽度
 height: 20, //一个格子的高度
 tr: 30, //行数
 td: 30 //列数
}
var snake = null, //Snake的实例
 food = null, //Food的实例
 game = null; //游戏的实例

//我们把蛇移动的整个区域设置成一个具有30列30行的网格坐标
//方块(格子)坐标位置
/**
0,0 (0,0)
20,0 (1,0)
40,0 (2,0)
*/
function Square(x, y, className) {
 this.x = x*config.width;
 this.y = y*config.height;
 this.className = className;
 this.contentDom = document.createElement('div');//该位置的方块对应的DOM元素
 this.contentDom.className = this.className;
 this.parent = document.getElementsByClassName("innerSnake")[0];

}
Square.prototype.create = function() { //创建方块并添加到页面
 this.contentDom.style.position = 'absolute';
 this.contentDom.style.width = config.width + 'px';
 this.contentDom.style.height = config.height + 'px';
 this.contentDom.style.left = this.x + 'px';
 this.contentDom.style.top = this.y + 'px';

 this.parent.appendChild(this.contentDom);
};
Square.prototype.remove = function() { //移除方块
 this.parent.removeChild(this.contentDom);
};

//蛇
function Snake() {
 this.head = null; //蛇头
 this.tail = null; //蛇尾
 this.pos = []; //二维数组,存储蛇身上每个节点(方块)
 this.directionKey = { //存储蛇走的方向
 left: { //往左走
 x: -1, //横坐标减1,一个坐标表示一个格子
 y: 0, //纵坐标不变
 rotate: 90
 },
 right: { //往右走
 x: 1,
 y: 0,
 rotate: -90
 },
 up: { //往上走
 x: 0,
 y: -1,
 rotate: 180
 },
 down: { //往下走
 x: 0,
 y: 1,
 rotate: 0 //蛇头图片方向,顺时针为正
 }
 }
}
Snake.prototype.init = function() { //初始化蛇
 //蛇头
 var snakeHead = new Square(2,0,"head");
 snakeHead.create(); //将蛇头添加到界面
 this.head = snakeHead; //存储蛇头信息
 this.pos.push([2,0]); //存储蛇头坐标

 //蛇的第1节身体
 var snakeBody1 = new Square(1,0,"body");
 snakeBody1.create(); //将蛇的第一节身体添加到界面
 this.pos.push([1,0]);

 //蛇的尾巴
 var snakeTail = new Square(0,0,"body");
 snakeTail.create(); //将蛇尾添加到界面
 this.tail = snakeTail; //存储蛇尾信息
 this.pos.push([0,0]);

 //形成链表关系
 snakeHead.prev = null; //蛇头的前面没有元素,指向null
 snakeHead.next = snakeBody1; //蛇头的后面有一节身体,其.next指针指向后面那节身体

 snakeBody1.prev = snakeHead; //蛇的第一节身体,.prev指向前面的蛇头snakeHead
 snakeBody1.next = snakeTail; //蛇的第一节身体,.next指向后面的身体,此时是蛇尾snakeTail

 snakeTail.prev = snakeBody1; //蛇尾,.prev指向前面的蛇身体snakeBody1
 snakeTail.next = null; //蛇尾后面没有元素,指向Null

 //初始蛇的走向,后面想改变蛇的走向即改变this.direction
 this.direction = this.directionKey.right; //默认向右走

};

//获取蛇头下一个位置对应的元素,根据元素做下一个动作
Snake.prototype.getNextPos = function() {
 var nextPos = [ //获取蛇头走的下一个点的坐标
  this.head.x / config.width + this.direction.x,
  this.head.y / config.height + this.direction.y
 ];

 //判断下一个点是自己or食物or围墙or无障碍?
 var self = false; //设置下一个点是否是自己
 this.pos.forEach(function(val) { //val即二位数组中的一个坐标
 if(val.toString() === nextPos.toString()) { //下一个坐标等于蛇全部身体的一个,即下一个点是自己
    self = true;
  }
 });
 if(self) {
 // console.log('撞到自己了!');
 this.collide.end.call(this); //game over

 return;
 } else if(nextPos[0] < 0 || nextPos[1] < 0 || nextPos[0] > config.td-1 || nextPos[1] > config.tr-1) {
 // console.log('撞到墙壁了!');
 this.collide.end.call(this); //game over

 return;
 } else if (food && food.pos[0] === nextPos[0] && food.pos[1] === nextPos[1]) {
 console.log('撞到食物了!');
 this.collide.eat.call(this);
 } else {
 // console.log('啥都没遇到!');
 this.collide.move.call(this, false); //注意:.call(this)重新设置this指向,使其指向当前实例对象Snake
 }
 

};

//处理碰撞后的事件
Snake.prototype.collide = {
 /*
 碰到自己or墙壁,游戏结束end();
 碰到食物,eat();
 啥都没遇到,move();
 */
 move: function(isEat) { //isEat 是否吃了食物,不是则删除蛇尾
 /*
 掐头去尾:
 create新蛇头,remove旧蛇头;
 create一个新身体,放在(替代)旧蛇头的位置;
 remove蛇尾,蛇尾prev的元素变成新蛇尾
 */
 var x = this.head.x / config.width + this.direction.x,
  y = this.head.y / config.height + this.direction.y;
 //声明一个新身体
 var newBody = new Square(this.head.x/config.width, this.head.y/config.height, "body");
 //更新链表关系
 newBody.next = this.head.next;
 newBody.next.prev = newBody;
 newBody.prev = null;

 this.head.remove(); //删除旧蛇头
 newBody.create(); //添加蛇身体,替代在旧蛇头位置

 //声明一个新蛇头(下一个走的点)
  var newHead = new Square(x, y, "head");
  //更新链表关系
  newHead.prev = null;
  newHead.next = newBody;
  newBody.prev = newHead;

  this.pos.unshift([x, y]); //更新蛇节点的坐标this.pos
  this.head = newHead; //更新this.head的信息
  
  newHead.contentDom.style.transform = `rotate(${this.direction.rotate}deg)`
  newHead.create(); //添加蛇头

  //删除蛇尾:吃食物则不删
  if(!isEat) { //没有吃食物,删除蛇尾
  this.tail.remove();
  this.tail = this.tail.prev;

  this.pos.pop(); //更新蛇节点坐标
  }
  // console.log(this.pos); //打印数组,验证
 },
 eat: function() {
 this.collide.move.call(this, true); //传参true,表示此时为吃操作
 food.remove(); //删除被吃掉的食物
 game.score ++; //记录分数
 createFood(); //此时再随机产生一个食物
 },
 end: function() {
 console.log('end');
 game.gameOver();
 }

}

snake = new Snake();

//创建食物
function createFood() {
 var x = null, y = null;
 var include = true; //表示食物的位置是否在蛇身上
 var random = function(max, min) { //产生一个随机数
 return Math.floor(Math.random()*(max - min + 1))
 };
 while(include) {
 x = random(config.tr - 1, 0);
 y = random(config.td - 1, 0);

 snake.pos.forEach(function(val) {
 if(x != val[0] && y != val[1]) {
 include = false;
 }
 });
 }

 //生成食物
 food = new Square(x, y, "food");
 food.pos = [x, y]; //记录食物坐标
 food.create();
}

//游戏逻辑
function Game() {
 this.score = 0; //分数
 this.timer = null; //计时器
}
Game.prototype.init = function() {
 snake.init();
 // snake.getNextPos(); //获取下一个点坐标
 createFood();

 document.onkeydown = function(event) {
 if(event.which == 37 && snake.direction != snake.directionKey.right) { 
  //鼠标左键,蛇不能是正在往右走
 snake.direction = snake.directionKey.left;
 } else if (event.which == 38 && snake.direction != snake.directionKey.down) { 
 //鼠标上键
 snake.direction = snake.directionKey.up;
 } else if (event.which == 39 && snake.direction != snake.directionKey.left) { 
 //鼠标右键
 snake.direction = snake.directionKey.right;
 } else if (event.which == 40 && snake.direction != snake.directionKey.up) { 
 //鼠标下键
 snake.direction = snake.directionKey.down;
 }
 }
 this.start();
};
game = new Game();
//开始游戏
Game.prototype.start = function() {
 this.timer = setInterval(function() {
 snake.getNextPos(); //获取下一个坐标点,做下一步动作
 }, 200);
};
//游戏结束
Game.prototype.gameOver = function() {
 console.log("gameOver");
 clearInterval(this.timer);
 var gameOver = document.querySelector('.gameOver');
 var gameScore = document.querySelector('.gameOver .score');
 gameOver.style.display = 'block'; //显示游戏结束界面
 gameScore.innerHTML = `${this.score}`; //将分数记入该界面
};

//开启游戏
function startGame() {
 var startBtn = document.querySelector('.btn button');
 var snakeWrap = document.querySelector('.snakeWrap');
 startBtn.onclick = function() {
 startBtn.parentNode.style.display = 'none'; //隐藏开始游戏界面
  snakeWrap.style.display = 'block'; //显示进入游戏的界面
  game.init();

 }
}
startGame();

主要用到链表数据结构

更多有趣的经典小游戏实现专题,也分享给大家:

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

Javascript 相关文章推荐
javascript web页面刷新的方法收集
Jul 02 Javascript
各种页面定时跳转(倒计时跳转)代码总结
Oct 24 Javascript
JavaScript的arguments对象应用示例
Sep 15 Javascript
jquery实现增加删除行的方法
Feb 03 Javascript
分享十五款 jQuery 社交网络分享插件
May 16 Javascript
jQuery实现网页顶部固定导航效果代码
Dec 24 Javascript
不得不分享的JavaScript常用方法函数集(下)
Dec 25 Javascript
JavaScript获取select中text值的方法
Feb 13 Javascript
Vue.js实战之组件的进阶
Apr 04 Javascript
利用ECharts.js画K线图的方法示例
Jan 10 Javascript
vue非父子组件通信问题及解决方法
Jun 11 Javascript
Vue SSR 即时编译技术的实现
May 06 Javascript
Javascript执行流程细节原理解析
May 14 #Javascript
使用npm命令提示: 'npm' 不是内部或外部命令,也不是可运行的程序的处理方法
May 14 #Javascript
javascript中的offsetWidth、clientWidth、innerWidth及相关属性方法
May 14 #Javascript
vue组件系列之TagsInput详解
May 14 #Javascript
ant-design-vue按需加载的坑的解决
May 14 #Javascript
JavaScript数组排序功能简单实现
May 14 #Javascript
Typescript3.9 常用新特性一览(推荐)
May 14 #Javascript
You might like
PHP中动态HTML的输出技术
2006/10/09 PHP
Ajax+PHP边学边练 之五 图片处理
2009/12/03 PHP
phpmyadmin配置文件现在需要绝密的短密码(blowfish_secret)的2种解决方法
2014/05/07 PHP
微信自定义菜单的创建/查询/取消php示例代码
2016/08/05 PHP
jQuery+php简单实现全选删除的方法
2016/11/28 PHP
JS实现自动定时切换的简洁网页选项卡效果
2015/10/13 Javascript
详解原生JavaScript实现jQuery中AJAX处理的方法
2016/05/10 Javascript
jQuery实现磁力图片跟随效果完整示例
2016/09/16 Javascript
JS动态计算移动端rem的解决方案
2016/10/14 Javascript
基于Javascript实现的不重复ID的生成器
2016/12/25 Javascript
详解微信小程序开发之——wx.showToast(OBJECT)的使用
2017/01/18 Javascript
JavaScript自动点击链接 防止绕过浏览器访问的方法
2017/01/19 Javascript
Node.js利用断言模块assert进行单元测试的方法
2017/09/28 Javascript
微信小程序开发摇一摇功能
2019/11/22 Javascript
[23:18]Spirit vs Liquid Supermajor小组赛A组 BO3 第二场 6.2
2018/06/03 DOTA
用python分割TXT文件成4K的TXT文件
2009/05/23 Python
python使用tensorflow保存、加载和使用模型的方法
2018/01/31 Python
Python cookbook(数据结构与算法)保存最后N个元素的方法
2018/02/13 Python
Python数据可视化处理库PyEcharts柱状图,饼图,线性图,词云图常用实例详解
2020/02/10 Python
HTML5无刷新改变当前url的代码
2017/03/15 HTML / CSS
Watchshop德国:欧洲在线手表No.1
2019/06/20 全球购物
英国Iceland杂货店:网上食品购物
2020/12/16 全球购物
PHP面试题附答案
2015/11/28 面试题
浅谈react路由传参的几种方式
2021/03/23 Javascript
新郎婚宴答谢词
2014/01/19 职场文书
学校联谊活动方案
2014/02/15 职场文书
中班中秋节活动反思
2014/02/18 职场文书
学员自我鉴定
2014/03/19 职场文书
物流管理专业毕业生求职信
2014/03/23 职场文书
小学生安全演讲稿
2014/04/25 职场文书
难忘的一课教学反思
2014/04/30 职场文书
廉洁教育学习材料
2014/05/19 职场文书
基层党建工作汇报材料
2014/08/15 职场文书
2015年乡镇残联工作总结
2015/05/13 职场文书
《认识年月日》教学反思
2016/02/19 职场文书
Java使用httpRequest+Jsoup爬取红蓝球号码
2021/07/02 Java/Android