js+jQuery实现贪吃蛇(堆栈处理按键)

效果图片
在这里插入图片描述实现思想:
  分析:
贪吃蛇游戏总体分三个部分:分别为头,背景,和蛇,只要把这三个部分组合起来,再加一些限制条件就是贪吃蛇游戏了,接下来咱们就分步骤去做贪吃蛇

第一步背景

 背景就是HTML的描绘,单纯的利用HTML和css去描绘背景

<!DOCTYPE html>
<html>
<head>
	<title>贪吃蛇</title>
	<style type="text/css">
		*{
			margin: 0;
			padding: 0;
		}
		.map{
			width: 800px;
			height: 600px;
			background-color: #7ca8d5;
			position: relative;
			border: 8px solid blue;
		}
	</style>
</head>
<body>
	<div class="map" id ="demo"></div>
</body>
</html>

 像上面这样一块背景图就做好了,接下来,我们在背景图内添加食物,切记,不能让食物跑出游戏边框外。

食物

 食物这里用到了JavaScript和jQuery,jQuery需要自行到网站上下载,然后链接到本文件,像这样

	<script src="jquery.js"></script>

这样你可以用jQuery了。
 我们在创造食物的时候,只创造一个食物对象即可,通过不断更新去随机食物的坐标,当创建食物的时候需要初始化一些参数

	var Food=function(color){
		this.ele=null; //这个是保存上一个的食物div,方便更新食物时删除
		this.x=0;
		this.y=0;
		this.width=20;
		this.height=20;
		this.color=color||"white";
	}

这样食物的对象和一些初始化数据就设定好了,写下来我们要做的是要写一个更新函数,当蛇吃到食物时候,食物要更新,并且把之前的食物残留要删除。

//随机生成食物的颜色;
var colors=["yellow","red","blue","pink","purple","green"];
var pos = parseInt( Math.random()*colors.length);
Food.prototype.init = function() {
		pos=parseInt( Math.random()*colors.length);
		this.color=colors[pos];
		this.remove();
		var $div = $("<div></div>");                  //通过jQuery去创建一个食物节点
		var $map = $(".map");
		$(".map").append($div);						//在背景图上添加这个食物
		$div.width(this.width);						//通过jQuery去设置食物的样式
		$div.attr("id","delete")
		$div.height(this.height);
		$div.css("background-color",this.color);
		//下面是随机食物的坐标位置
		this.x=parseInt(Math.random()*($map.width()/this.width))*this.width+8;
		this.y=parseInt(Math.random()*($map.height()/this.height))*this.height+8;
		$div.offset({left:this.x,top:this.y});
	};
Food.prototype.remove=function(){
		$("div").remove("#delete");
	}

 随后我们去创建食物这个对象,需要传入一个颜色参数

	var food = new Food(colors[pos]);
	food.init();

 向上面这样即可随机位置创建随机颜色的食物,接下来我们创造一条蛇

 在创建蛇的时候我们考虑一下蛇都可以做什么:首先,蛇可以移动,并且会有一个默认方向,蛇还会移动,蛇会在移动的过程中去吃掉食物,蛇吃掉食物之后身体会增长,蛇不能吃到自己的身体,蛇不能撞墙,食物不能出现在蛇的身体上,蛇在移动时候不能反方向移动,蛇在移动一个方向时候不能在同一频率内向其他方向移动
考虑以上的一些性质之后我们就去创造蛇

var OperationSet=[];
function snake(direction){
		this.ele=[];	//存储蛇的移动上一次路径,方便删除其路径
		this.width=20;
		this.height=20;
		this.body=[
		{x:3,y:2,color:"white"},
		{x:2,y:2,color:"red"},
		{x:1,y:2,color:"red"}];
		OperationSet.push("right");
	}

 创造蛇对象时候要初始化一些必要数据,并且给蛇一定长度,接下来去描绘蛇

Snake.prototype.init = function() {
		this.remove(); //描绘之前,需要清除上一次蛇的位置,这样蛇才能动起来
		for (var i = 0; i < this.body.length; i++) {
			var obj = this.body[i];
			var $div=$("<div></div>");
			var $map = $(".map");
			$map.append($div);
			$div.width(this.width);
			$div.height(this.height);
			$div.attr("position","absolute");
			$div.attr("id","bd");
			$div.css("left",obj.x*this.width+'px');
			$div.css("position","absolute");
			$div.css("top",obj.y*this.height+'px');
			$div.css("background-color",obj.color);
			this.ele.push($div);
		}
	};

这部分是对蛇的初始化和描绘,接下来是蛇的动作和性质

Snake.prototype.move = function(food,event) {
		var i = this.body.length-1;
		for( ; i>0 ; i--){
			this.body[i].x=this.body[i-1].x;
			this.body[i].y=this.body[i-1].y;
		}
		switch(this.direction){
			case "right":
				this.body[0].x += 1;
				break;
			case "left":
				this.body[0].x -= 1;
				break;
			case "top":
				this.body[0].y -= 1;
				break;
			case "down":
				this.body[0].y += 1;
				break;
		}
		this.eat();
	};
	Snake.prototype.eat=function(){
		var snakex = this.body[0].x*this.width+8;
		var snakey = this.body[0].y*this.height+8;
		var foodx=food.x;
		var foody=food.y;
		if(snakex==foodx&&snakey==foody){
			var last = this.body[this.body.length-1];
			this.body.push({x:last.x,y:last.y,color:food.color}); //蛇吃到食物后身体增长
			food.init();
			for(var i=0;i<this.body.length;i++){
			//食物不能出现在蛇的身体上
				while(food.x==this.body[i].x&&food.y==this.body[i].y){
					food.init();
				}
			}
		}

		for(var i=1;i<this.body.length;i++){
			var snakeheadx=this.body[0].x;
			var snakeheady=this.body[0].y;
			if(snakeheadx==this.body[i].x && snakeheady==this.body[i].y){
				alert('over');
				clearInterval(handler);    //如果蛇迟到自己身体结束游戏,清除循环函数的句柄
				return;
			}
			if(snakeheadx<0||snakeheadx>=(800/this.width)||snakeheady<0||snakeheady>=600/(this.height)){
				alert('over');	//如果蛇撞到游戏边框,清除循环函数的句柄
				clearInterval(handler);
				return;
			}
			console.log(snakeheady);
		}
		
		this.init();
	}
	Snake.prototype.remove=function(){
		for(var i = 0;i<this.ele.length;i++){
			$("#bd").remove();
		}
		this.ele.length=0;
	}

 接下来去新建一个蛇的对象

var snake = new Snake();

接下来就是按键处理,在按键时候,把所有的连续放到堆栈里面,通过弹栈方式出处理按键处理,接下里就是按键的处理


document.addEventListener("keydown",function (e) {
		switch (e.keyCode) {
            case 37:
            	if(OperationSet.length==0 && snake.direction!="right"){
                    OperationSet.push("left");
                }else if (OperationSet[OperationSet.length-1]!="right" && OperationSet[OperationSet.length-1]!=undefined && OperationSet[OperationSet.length-1] != "left")
     				OperationSet.push("left");
                break;
        	case 40:
            	if(OperationSet.length==0 && snake.direction!="top"){
                	OperationSet.push("down");
                }else if(OperationSet[OperationSet.length-1]!="top" && OperationSet[OperationSet.length-1]!=undefined && OperationSet[OperationSet.length-1] !="down")
                	OperationSet.push("down");
                break;
                
        	case 39:
                if(OperationSet.length==0 && snake.direction!="left"){
                	OperationSet.push("right");
                }else if(OperationSet[OperationSet.length-1]!="left" && OperationSet[OperationSet.length-1]!=undefined && OperationSet[OperationSet.length-1] !="right")
                	OperationSet.push("right");
     			break;
            case 38:
                if(OperationSet.length==0 && snake.direction!="down"){
                	OperationSet.push("top");
                }else if(OperationSet[OperationSet.length-1]!="down" && OperationSet[OperationSet.length-1]!=undefined && OperationSet[OperationSet.length-1] !="top" )
                	OperationSet.push("top");
                break;    
        }

接下里要处理栈里面的数据,去更改蛇的移动方向如下

var directionFirst,directionSecond;
	handler = setInterval(function(){
		directionFirst = OperationSet.shift();
		if(directionFirst!=directionSecond && directionFirst!=undefined){
			directionSecond = directionFirst;
			snake.direction=directionFirst;
		}else {
			snake.direction=directionSecond;
		}
		console.log(OperationSet[OperationSet.length-1]);
		snake.move();
	},200);

把上面的代码全部结合起来就是下面这样的

<!DOCTYPE html>
<html>
<head>
	<title>贪吃蛇</title>
	<meta charset="utf-8">
	<style type="text/css">
		*{
			margin: 0;
			padding: 0;
		}
		.map{
			width: 800px;
			height: 600px;
			background-color: #7ca8d5;
			position: relative;
			border: 8px solid blue;
		}
	</style>
</head>
<body>
<div class="map" id="demo"></div>
</body>
<script src="jquery.js"></script>
<script type="text/javascript">
	var handler;
	var OperationSet=[];
	var colors=["yellow","red","blue","pink","purple","green"];
	var pos = parseInt( Math.random()*colors.length);
	var Food=function(color){
		this.ele=null;
		this.x=0;
		this.y=0;
		this.width=20;
		this.height=20;
		this.color=color||"white";
	}
	Food.prototype.init = function() {
		pos=parseInt( Math.random()*colors.length);
		this.color=colors[pos];
		this.remove();
		var $div = $("<div></div>");
		var $map = $(".map");
		$(".map").append($div);
		$div.width(this.width);
		$div.attr("id","delete")
		$div.height(this.height);
		$div.css("background-color",this.color);
		this.x=parseInt(Math.random()*($map.width()/this.width))*this.width+8;
		this.y=parseInt(Math.random()*($map.height()/this.height))*this.height+8;
		$div.offset({left:this.x,top:this.y});
	};
	Food.prototype.remove=function(){
		$("div").remove("#delete");
	}
	var food = new Food(colors[pos]);
	food.init();
	function Snake(direction){
		this.ele=[];
		this.width=20;
		this.height=20;
		this.body=[
		{x:3,y:2,color:"white"},
		{x:2,y:2,color:"red"},
		{x:1,y:2,color:"red"}];
		OperationSet.push("right");
	}
	Snake.prototype.init = function() {
		this.remove();
		for (var i = 0; i < this.body.length; i++) {
			var obj = this.body[i];
			var $div=$("<div></div>");
			var $map = $(".map");
			$map.append($div);
			$div.width(this.width);
			$div.height(this.height);
			$div.attr("position","absolute");
			$div.attr("id","bd");
			$div.css("left",obj.x*this.width+'px');
			$div.css("position","absolute");
			$div.css("top",obj.y*this.height+'px');
			$div.css("background-color",obj.color);
			this.ele.push($div);
		}
	};
	Snake.prototype.move = function(food,event) {
		var i = this.body.length-1;
		for( ; i>0 ; i--){
			this.body[i].x=this.body[i-1].x;
			this.body[i].y=this.body[i-1].y;
		}
		switch(this.direction){
			case "right":
				this.body[0].x += 1;
				break;
			case "left":
				this.body[0].x -= 1;
				break;
			case "top":
				this.body[0].y -= 1;
				break;
			case "down":
				this.body[0].y += 1;
				break;
		}
		this.eat();
		

	};
	Snake.prototype.eat=function(){
		var snakex = this.body[0].x*this.width+8;
		var snakey = this.body[0].y*this.height+8;
		var foodx=food.x;
		var foody=food.y;
		if(snakex==foodx&&snakey==foody){
			var last = this.body[this.body.length-1];
			this.body.push({x:last.x,y:last.y,color:food.color});
			food.init();
			for(var i=0;i<this.body.length;i++){
				while(food.x==this.body[i].x&&food.y==this.body[i].y){
					food.init();
				}

			}
		}

		for(var i=1;i<this.body.length;i++){
			var snakeheadx=this.body[0].x;
			var snakeheady=this.body[0].y;
			if(snakeheadx==this.body[i].x && snakeheady==this.body[i].y){
				alert('吃到自己 over');
				clearInterval(handler);
				return;
			}
			if(snakeheadx<0||snakeheadx>=(800/this.width)||snakeheady<0||snakeheady>=600/(this.height)){
				alert('撞墙 over');
				clearInterval(handler);
				return;
			}
		}
		
		this.init();
	}
	Snake.prototype.remove=function(){
		for(var i = 0;i<this.ele.length;i++){
			$("#bd").remove();
		}
		this.ele.length=0;
		
	}
	var snake = new Snake();
	var directionFirst,directionSecond;
	handler = setInterval(function(){
		directionFirst = OperationSet.shift();
		if(directionFirst!=directionSecond && directionFirst!=undefined){
			directionSecond = directionFirst;
			snake.direction=directionFirst;
		}else {
			snake.direction=directionSecond;
		}
		snake.move();
	
	},200);
	
	document.addEventListener("keydown",function (e) {
		switch (e.keyCode) {
            case 37:
            	if(OperationSet.length==0 && snake.direction!="right"){
                    OperationSet.push("left");
                }else if (OperationSet[OperationSet.length-1]!="right" && OperationSet[OperationSet.length-1]!=undefined && OperationSet[OperationSet.length-1] != "left")
     				OperationSet.push("left");
                break;
        	case 40:
            	if(OperationSet.length==0 && snake.direction!="top"){
                	OperationSet.push("down");
                }else if(OperationSet[OperationSet.length-1]!="top" && OperationSet[OperationSet.length-1]!=undefined && OperationSet[OperationSet.length-1] !="down")
                	OperationSet.push("down");
                break;
                
        	case 39:
                if(OperationSet.length==0 && snake.direction!="left"){
                	OperationSet.push("right");
                }else if(OperationSet[OperationSet.length-1]!="left" && OperationSet[OperationSet.length-1]!=undefined && OperationSet[OperationSet.length-1] !="right")
                	OperationSet.push("right");
     			break;
            case 38:
                if(OperationSet.length==0 && snake.direction!="down"){
                	OperationSet.push("top");
                }else if(OperationSet[OperationSet.length-1]!="down" && OperationSet[OperationSet.length-1]!=undefined && OperationSet[OperationSet.length-1] !="top" )
                	OperationSet.push("top");
                break;    
        }

</script>
</html>

当然这个按键处理目前存在bug,有能力的朋友可以指正哦。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值