一、代码需要完成的需求
1.把游戏页面的画面框分割成一个个方块,设置坐标

2.构造Square函数生成方块对象:
该对象具有的宽高属性、类名;
原型上的方法有:创建相应类名的方块DOM,删除方块DOM

3.通过调用Square构造函数帮忙生成蛇对象:
属性:蛇头的方向、保存整条蛇数组、蛇头、蛇尾;
原型上的方法:初始化函数 调用Square创建蛇头、蛇身、蛇尾等放入数 组,再建立链表关系;蛇的下一步:蛇撞墙、蛇咬到自己、蛇要吃、蛇要移动:采用链表进行移动,参数为是否吃到食物,是就不删除蛇尾,反之删除。

4 创建食物对象:随机产生,不产生在蛇的身上,当蛇撞上食物时,删除原先食物,再调用square创建新食物对象

5.游戏逻辑:
点击“开始游戏”按钮,按钮和遮罩层消失,开启定时器,开始游戏
点击游戏页面暂停游戏,关闭定时器;点击“继续游戏”,再次开启定时器
上下左右键控制蛇头方向
游戏结束时弹出分数,点击确定后回到初始界面

二、游戏画面展示

javascript 贪吃蛇小游戏练习html js做贪吃蛇_ide


三、代码展示

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<title>贪吃蛇小游戏</title>
	<style type="text/css">
		*{
			margin:0;
			padding: 0; 
		}
		#content{
			width: 600px;
			height: 600px;
			/*background-color: #3c3c3c;*/
			margin: 50px auto;
			position: relative;
		}
		#content .startBtn,
		#content .pauseBtn{
			width: 100%;
			height: 100%;
			background-color: rgba(0,0,0,0.2);
			position: absolute;
			left: 0;
			top: 0;

			z-index: 2;
		}
		#content .startBtn button,
		#content .pauseBtn button{
			width: 200px;
			height: 80px;

			background-color:#3c3c3c;
			border:none; 
			border-radius: 40px;

			cursor: pointer;
			outline: none;

			position: absolute;
			left: 50%;
			top: 50%;
			margin-left: -100px;
			margin-top: -40px;

			color: #fff;
			font-size: 32px;
		}
		#content .pauseBtn,
		#content .pauseBtn button{
			display: none;
		}
		#content .innerSnake{
			width: 100%;
			height: 100%;
			background-color: rgba(0,0,0,0.5);
			position: absolute;
			left: 0;
			top: 0;
		}

		#content .innerSnake .food,
		#content .innerSnake .snakeBody,
		#content .innerSnake .snakeHead{
			/*width: 20px;
			height:20px;*/
			border-radius: 50%;
			/*background-color: 	#000;*/
			/*background-color: 	#2F4F4F*/
		}
		#content .innerSnake .food{
			/*border-radius: 50%;*/
			background-color:	#F0FFFF;
		}

		#content .innerSnake .snakeHead{
			background-color: 	#000;
		}
		#content .innerSnake .snakeBody{
			background-color: #fff;
		}
	</style>
</head>
<body>

	<div id="content">
		<div class="startBtn"><button>开始游戏</button></div>
		<div class="pauseBtn"><button>继续游戏</button></div>
		<div class="innerSnake">
			<div class="food"></div>
			<div class="snakeHead"></div>
			<div class="snakeBody"></div>
		</div>
	</div>

	<script type="text/javascript">
		// 方块属性,创建DOM方块,删除DOM方块
		// 蛇的方向、数组、蛇头、蛇尾,初始化函数调用Square创建蛇头、蛇身、蛇								尾等放入数组,再建立链表关系,
		// 蛇的下一步:
		// 	蛇撞墙
		// 	蛇咬到自己
		// 	蛇要吃
		// 	蛇要移动:采用链表进行移动,参数为是否吃到食物,是就不				删除蛇尾,反之删除。
		// 创建食物对象:随机产生,不产生在蛇的身上,当蛇撞上食物时,删除原先,
		// 				创建新食物对象
		// 游戏流程:初始化,
		var config={
			sw : 20,
			sh : 20,
			tr : 30,
			td : 30
		}
		var snake = null,
			food = null,
			game = null;

		// 方块的属性:坐标和类名
		function Square(x,y,classname){
			this.x = x*config.sw;
			this.y = y*config.sh;
			this.className = classname;

			this.Dom = document.createElement('div');
			this.Dom.className = this.className;
			this.parentNode = document.getElementsByClassName('innerSnake')[0];
		}
		Square.prototype.create = function(){
			// 设置方块上的基本样式
			this.Dom.style.position = 'absolute';
			this.Dom.style.width = config.sw + 'px';
			this.Dom.style.height = config.sh + 'px';
			this.Dom.style.left = this.x  + 'px';
			this.Dom.style.top = this.y  + 'px';

			this.parentNode.appendChild(this.Dom);
		}
		Square.prototype.remove = function(){
			this.parentNode.removeChild(this.Dom)
		}

		function Snake(){
			this.head = null;
			this.tail = null;
			this.pos = [];

			// 没有实例化对象,你建立什么建表结构
			// this.head.next = null;
			// this.head.prev = this.tail.next;
			// this.tail.next.next = this.head;
			// this.tail.next.prev = this.tail;
			// this.tail.prev = null;

			// this.direction = 'right';
			this.directionKey = {
				right:{
					x:1,
					y:0
				},
				left:{
					x:-1,
					y:0
				},
				up:{
					x:0,
					y:-1
				},
				down:{
					x:0,
					y:1
				}
			}
		}
		Snake.prototype.init = function(){
			var snakeHead = new Square(2,0,"snakeHead");
			snakeHead.create();
			this.head = snakeHead;
			this.pos.push([2,0]);

			var snakeBody1 = new Square(1,0,'snakeBody');
			snakeBody1.create();
			this.pos.push([1,0]);

			var snakeBody2 = new Square(0,0,'snakeBody');
			snakeBody2.create();
			this.pos.push([0,0]);
			this.tail = snakeBody2;

			this.head.next = null;
			this.head.prev = snakeBody1;
			snakeBody1.next = this.head;
			snakeBody1.prev = this.tail;
			this.tail.next = snakeBody1;
			this.tail.prev = null;
			// console.log(this.head.next,this.head.prev,snakeBody1.next ,snakeBody1.prev ,this.tail.next,this.tail.prev)

			// 默认向右走,初始化
			this.direction = this.directionKey.right;
		}
		Snake.prototype.nextStep = function(){
			var nextSp = [
							this.head.x/config.sw + this.direction.x,
							this.head.y/config.sh + this.direction.y
						]
			// 是否要到自己
			var note = false;

			this.pos.forEach(function(value){
				if(value[0]===nextSp[0] && value[1]===nextSp[1]){
					// console.log('咬到自己了');
					note = true;
					// this.collide.end.call(this);
					// return;
				}
			})

			if(note){
				this.collide.end.call(this);
				return;
			}
			// 是否撞墙
			else if(nextSp[0] < 0 || nextSp[0] >= config.td || nextSp[1] < 0 || nextSp[1] >= config.tr){
				// console.log('撞墙了');
				this.collide.end.call(this);
				return;
			}

			//是否吃到食物
			else if(food && nextSp[0]===food.pos[0] && nextSp[1]===food.pos[1]){
				this.collide.eat.call(this);
				return;
			}

			//蛇要移动
			else {
				this.collide.move.call(this,false);
			}
		}
		//处理各个事件的函数集合对象
		Snake.prototype.collide = {
			move : function(isEat){
				var x = this.head.x/config.sw + this.direction.x,
					y = this.head.y/config.sh + this.direction.y;

				var newBody = new Square(this.head.x/config.sw,
					this.head.y/config.sh, 'snakeBody');
				
				newBody.next = null;
				newBody.prev = this.head.prev;
				newBody.prev.next = newBody;

				this.head.remove();
				newBody.create();

				var newHead = new Square(x,y,'snakeHead');
				newHead.next = null;
				newHead.prev = newBody;
				newBody.next = newHead;

				// console.log(newHead.next,newHead.prev,newBody.next,newBody.prev);
				//忘记把新坐标放进数组了
				this.pos.unshift([x,y]);
				this.head = newHead;
				newHead.create();
				

				if(!isEat){
					this.tail.remove();
					this.tail = this.tail.next;
					//这边也是,忘记删除数组末尾
					this.pos.pop();
				}
			},
			end:function(){
				game.over();
			},
			eat:function(){
				this.collide.move.call(this,true);
				food.remove();
				game.score++;
				createFood();
			}
		}

		snake = new Snake();
		// snake.init();
		// snake.nextStep();
		//创建食物
		function createFood(){
			var x = null,
				y = null;

			var flag = true; 
			while(flag){
				x = Math.floor(Math.random()*(config.td-1));
				y = Math.floor(Math.random()*(config.tr-1));

				snake.pos.forEach(function(value){
					if(x!==value[0] || y!==value[1]){
						flag = false;
						// break;
					}
				})
			}

			// food.remove();
			food = new Square(x,y,'food');
			// food.remove();
			food.pos = [x,y];
			// console.log('食物坐标:'+food.pos);
			food.create();
		}
		// createFood();

		//游戏逻辑
		function Game(){
			this.score = 0;
			this.timer = null;
		}
		Game.prototype.init = function(){
			//在这里出了大问题,如果没有snake先初始化的话,createfood函数调用时无法获得snake里的pos数组,无法遍历,所以一直加载不出来 将init 和 createfood 更换位置就能正常实现了
			snake.init();
			createFood();
			// console.log('here');
			document.onkeydown = function(e){
				if(e.which == 37 && snake.direction != snake.directionKey.right){
					snake.direction = snake.directionKey.left;
				}
				else if(e.which == 38 && snake.direction != snake.directionKey.down){
					snake.direction = snake.directionKey.up;
				}
				else if(e.which == 39 && snake.direction != snake.directionKey.left){
					snake.direction = snake.directionKey.right;
				}
				else if(e.which == 40 && snake.direction != snake.directionKey.up){
					snake.direction = snake.directionKey.down;
				}
			}
			this.start();
		};
		// // console.log('开始');
		Game.prototype.start = function(){
			this.timer = setInterval(function(){
				snake.nextStep();
			},200);
		}
		Game.prototype.pause = function(){
			clearInterval(this.timer);
		}
		// // console.log('结束');
		Game.prototype.over = function(){
			clearInterval(this.timer);
			alert('Game over\n你的分数是:'+this.score);
			// window.reload();
			var innerSnake = document.querySelector('#content .innerSnake');
			innerSnake.innerHTML = '';

			snake = new Snake();
			game = new Game();

			var startBtn = document.querySelector('#content .startBtn button');
			var startMark = document.querySelector('#content .startBtn');

			startBtn.style.display = 'block';
			startMark.style.display = 'block';
		}

		game = new Game();
		// game.init();
		function begin(){
			var startBtn = document.querySelector('#content .startBtn button');
			var startMark = document.querySelector('#content .startBtn');
			// var self = this;
			startBtn.onclick = function(){
				startBtn.style.display = 'none';
				startMark.style.display = 'none';
				// console.log('1')
				game.init();
			}
		}
		function stop(){
			var innerSnake = document.querySelector('#content .innerSnake');
			var pauseBtn = document.querySelector('#content .pauseBtn button');
			var pauseMark = document.querySelector('#content .pauseBtn');

			innerSnake.onclick = function(){
				game.pause();
				pauseBtn.style.display = 'block';
				pauseMark.style.display = 'block';
			}

			pauseBtn.onclick = function(){
				game.start();
				pauseBtn.style.display = 'none';
				pauseMark.style.display = 'none';
			}
		}
		begin();
		stop();

	</script>
</body>
</html>