js实现贪吃蛇以及自动寻找食物及项目报告

快到期末了也是老师喊写一个js贪吃蛇报告.所以就写了下,下面分享出来.

直接上代码了,除了自动寻找食物的bfs没有注释,其它注释都挺全的.这个只是简单的实现了,并没有很好的优化.后面有报告及源码,直接运行即可成功.

  1. 先来把截图

  2. HTML部分
    <!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>贪吃蛇</title>
    		<link rel="stylesheet" href="css.css">
    		
    		<script src="sanke.js"></script>
    	</head>
    	<body bgcolor="skyblue">
    		<div style="scrollbar-width: none;">
    		<h1 class="h1"><span class="sp1">贪</span><span class="sp2">吃</span><span class="sp3">蛇</span><span class="sp4">大</span><span
    			 class="sp5">战</span></h1>
    		<p class="p"><span>得分:</span><span id="fenshu">0</span></p>
    		<p class="p p2"><span>用时:</span><span id="times">0</span></p>
    		<div id="div1"></div>
    		<p id="select">难度:
    			<select id="selectop">
    				<option value="100">慢</option>
    				<option value="70">中</option>
    				<option value="30">快</option>
    			</select>
    		</p>
    		<input type="button" value="点击手动控制" id="but">
    		<input type="button" value="点击自动控制" id="autobut">
    		</div>
    	</body>
    </html>
    

     

  3. CSS部分
    body{
    	overflow-x: hidden;
    	overflow-y: hidden;
    }
    #div1 {
    	
    	width: 500px;
    	height: 500px;
    	background: linear-gradient(#6ac1e9, #02293d);
    	/* background-color: #000; */
    	margin: 10px auto;
    	position: relative;
    }
    
    #div1 span {
    	display: inline-block;
    	width: 20px;
    	height: 20px;
    	background-color: #38D138;
    	position: absolute;
    	/* border-radius: 50%; */
    	border: 2px solid #fff;
    	;
    }
    
    #div1 i {
    	display: block;
    	width: 20px;
    	height: 20px;
    	/* border-radius: 50%; */
    	border: 2px solid #fff;
    	;
    	background-color: #E6AC0E;
    	position: absolute;
    }
    
    h1 {
    	text-align: center;
    }
    
    .p {
    	position: absolute;
    	display: block;
    	width: 100px;
    	font-size: 20px;
    	left: 50px;
    }
    
    .p2 {
    	top: 50px;
    	width: 150px;
    }
    
    #fenshu {
    	color: #2A15E7;
    	position: relative;
    	transition: all .5s;
    	opacity: 1;
    }
    
    #select {
    	font-size: 20px;
    	position: absolute;
    	top: 130px;
    	left: 50px;
    }
    
    #but {
    	position: absolute;
    	top: 200px;
    	left: 50px;
    	color: #fff;
    	background-color: #337ab7;
    	border: 1px solid #2e6da4;
    	border-radius: 3px;
    	padding: 5px 10px;
    	cursor: pointer;
    	opacity: .9;
    	transition: all .5s;
    }
    #autobut {
    	position: absolute;
    	top: 250px;
    	left: 50px;
    	color: #fff;
    	background-color: #337ab7;
    	border: 1px solid #2e6da4;
    	border-radius: 3px;
    	padding: 5px 10px;
    	cursor: pointer;
    	opacity: .9;
    	transition: all .5s;
    }
    #but:hover {
    	opacity: 1;
    }
    

     

  4. JS部分
    window.onload = function() {
    	
    	var autotype = false;
    	var maxn = 25;
    	var autoMap = new Array();
    	var autoVis = new Array();
    	var autoDis = [[-1,0],[0,1],[1,0],[0,-1]];// u r d l ;
    	var autoStr = new Array();
    	var autofoodx=0;
    	var autofoody=0;
    	var Str="";
    	var v=100;
    	var bug=true;
    
    	var div1 = document.getElementById("div1");       //获取地图的区域块
    	var fenshu = document.getElementById("fenshu");//获取分数标签
    	var select = document.getElementById("selectop");//获取等级选择标签
    	var but = document.getElementById("but");//获取点击开始按钮标签
    	var times = document.getElementById("times");//获取时间显示标签
    	var arr = [];//创建一个数组,储存蛇身节点
    	var size = 20;//定义的蛇节点移动距离单位,为20个像素
    	var dir = "right";//初始化蛇向右移动
    	var speed = 100;//蛇移动的初始速度
    	var s = 0;//统计时间变量
    	var gameIsPlay = false;//游戏是否结束 为false为结
    	var tip=0;
    	
    	
    	function init(){
    		Str="";
    		ans=0;
    		for (var i = 0; i < maxn; i++) {
    			autoMap[i] = new Array();
    			autoVis[i] = new Array();
    			autoStr[i] = new Array();
    			for(var j = 0;j < maxn; j++){
    				autoMap[i][j] = 0;
    				autoVis[i][j] = 1;
    				autoStr[i][j] = "";
    			}
    		}
    		for(var i = 0;i<arr.length;i++){
    			var x = arr[i].style.left;
    			var y = arr[i].style.top;
    			autoMap[parseInt(y)/size][parseInt(x)/size] = 1;
    		}
    		autoMap[autofoodx/size][autofoody/size] = 2;	
    	}
    	
    	function NNode(x,y){
    		this.x=x;
    		this.y=y;
    	}
    	
    	function bfs() {
    		init();
    		var head = arr[arr.length-1];
    		var x = head.style.left;
    		var y = head.style.top;
    		var xx = parseInt(y)/size;
    		var yy = parseInt(x)/size;
    		var node = new NNode(xx,yy);
    	    var queue = [];
    		queue.push(node);
    		autoVis[xx][yy] = 0;
    		
    	    while(queue.length!=0) {
    			var temp = queue.shift();
    			if(autoMap[temp.x][temp.y]==2&&bug==true){
    				Str=autoStr[temp.x][temp.y];
    				// console.log(Str);
    				break;
    			}
    			if(autoMap[temp.x][temp.y]==0&&bug==false){
    				Str=Str=autoStr[temp.x][temp.y];
    				break;
    			}
    	        // 分层遍历队列,没有目标元素则删除该层元素,继续遍历下一层
    	        for(var i =0; i<4; i++) {//autoDis = [[0,1],[1,0],[0,-1],[-1,0]];//u r d l;
    	            var dx =temp.x+autoDis[i][0];
    				var dy =temp.y+autoDis[i][1];
    	            if(dx>=0&&dx<maxn&&dy>=0&&dy<maxn&&autoMap[dx][dy]!=1&&autoVis[dx][dy]==1){
    					autoVis[dx][dy] = 0;
    					var node1 = new NNode(dx,dy);
    					if(i==0){
    						autoStr[dx][dy] += autoStr[temp.x][temp.y]+"u";
    					}
    					if(i==1){
    						autoStr[dx][dy]+= autoStr[temp.x][temp.y]+"r";
    					}
    					if(i==2){
    						autoStr[dx][dy]+= autoStr[temp.x][temp.y]+"d";
    					}
    					if(i==3){
    						autoStr[dx][dy]+= autoStr[temp.x][temp.y]+"l";
    					}
    					queue.push(node1);
    	            }
    	        }
    	    }
    		if(Str[ans]==undefined){
    			var maxlen=0;
    			for (var i = 0; i < maxn; i++) {
    				for(var j = 0;j < maxn; j++){
    					if(maxlen<autoStr[i][j].length){
    						maxlen=autoStr[i][j].length;
    						Str=autoStr[i][j];
    						console.log(Str);
    					}
    				}
    			}
    			// bug=false;
    			// bfs();
    			// console.log("s");
    		}else{
    			bug=true;
    		}
    	}
    	
    	//生成一条蛇
    	function createSnake() {
    		for (var i = 0; i < 4; i++) {//初始化蛇身长为4个节点
    			//生成一个span
    			var span = document.createElement("span");//用一个span标签作为一个蛇的节点
    			arr.push(div1.appendChild(span));//将节点放入arr数组中
    			span.style.left = i * size + "px";//初始化蛇节点的横坐标位置
    			span.style.top = 0;//初始化蛇节点的纵坐标位置
    		}
    	}
    	//移动小蛇
    	function moveSnake() {
    		
    		if(Str[ans]=='r'){
    			dir = "right";
    		}
    		if(Str[ans]=='d'){
    			dir = "bottom";
    		}
    		if(Str[ans]=='l'){
    			dir = "left";
    		}
    		if(Str[ans]=='u'){
    			dir = "top";
    		}
    		var head = arr[arr.length - 1];//取出数组的最后一个蛇节点当做蛇头节点
    		var Left = head.style.left;//left,top获取蛇头节点的位置(坐标也可)
    		var Top = head.style.top;
    		if (dir == "right") {//如果按的是右键,则相当于蛇节点的横坐标增加,纵坐标不变,
    			arr[0].style.left = parseInt(Left) + size + "px";//相当于节点的横坐标left加上20个像素单位,即蛇节点向右移动
    			arr[0].style.top = parseInt(Top) + "px";//相当于蛇节点的纵坐标不变
    		}
    		if (dir == "left") {//原理同上,则相当于蛇节点的横坐标减少,纵坐标不变
    			arr[0].style.left = parseInt(Left) - size + "px";
    			arr[0].style.top = parseInt(Top) + "px";
    		}
    		if (dir == "bottom") {//原理同上 则相当于蛇节点的横坐标不变,纵坐标增加
    			arr[0].style.left = parseInt(Left) + "px";
    			arr[0].style.top = parseInt(Top) + size + "px";
    		}
    		if (dir == "top") {//原理同上 则相当于蛇节点的横坐标不变,纵坐标减少
    			arr[0].style.left = parseInt(Left) + "px";
    			arr[0].style.top = parseInt(Top) - size + "px";
    		}
    		var kk=true;
    		
    		//碰撞检测
    		var fen = 10;//定义一个食物值10分
    		if (parseInt(arr[0].style.left) == x && parseInt(arr[0].style.top) == y) {
    			//得分
    			scoreAnimation()
    			fenshu.innerHTML = (Number(fenshu.innerHTML) + fen);//更新分数
    			// fenshu.className = "hide";
    			addspan();
    			createfood();//创建食物
    			// bfs();
    		}
    		//死亡检测---边界
    		if (parseInt(arr[0].style.left) >480 || parseInt(arr[0].style.left) < 0 || parseInt(arr[0].style.top) > 480 || parseInt(arr[0].style.top) < 0) {
    			if(tip>=arr.length+50){
    				gameIsPlay = false;
    				if(autotype)
    					clearInterval(h);
    				clearInterval(t);
    			}
    			clearInterval(gameTime);
    			tip++;
    		}
    
    		//碰撞自身死亡
    		arr2 = [];
    		for (var j = 0; j < arr.length; j++) {
    			var createObject = {};
    			createObject.x = parseInt(arr[j].style.left);
    			createObject.y = parseInt(arr[j].style.top);
    			arr2.push(createObject);	
    		}
    		arr2.pop();
    		//让蛇头和新数组的值比对
    		for (var i = 1; i < arr2.length; i++) {
    			if (parseInt(Left) == arr2[i].x && parseInt(Top) == arr2[i].y) {
    				if(tip==0){
    					if(autotype)
    						clearInterval(h);
    				}
    				if(tip>=arr.length+2){
    					gameIsPlay = false;
    					clearInterval(t);
    				}
    				clearInterval(gameTime);
    				tip++;	
    				break;
    			}
    		}
    		arr.push(arr.shift());
    	}
    
    	//分数动画
    	function scoreAnimation() {
    		fenshu.style.top = "-25px";
    		fenshu.style.opacity = 0;
    		setTimeout(function() {
    			fenshu.style.top = 0;
    			fenshu.style.opacity = 1;
    		}, 500)
    	}
    	//游戏开始
    	function ready() {
    		createSnake();//创建蛇身
    		createfood();//创建食物	
    		gameIsPlay = true//将游戏状态置为true
    	}
    	//清空数据
    	function clear() {
    		tip=0;
    		ans=0;
    		dir = "right";
    		arr = [];
    		arr2 = [];
    		speed = select.value;
    		fenshu.innerHTML = 0;
    		s = 0;
    		div1.innerHTML = "";
    		times.innerHTML = 0;
    
    	}
    	//难度选择
    	select.onchange = function() {
    		v = this.value;//改变速度
    	}
    	//点击手动控制
    	but.onclick = function() {
    		autotype = false;
    		if (!gameIsPlay) {//当游戏未开始点击开始按钮才有效
    			clear();
    			t = setInterval(function() {
    				moveSnake()
    			}, v)
    			clock();
    			ready();
    		}
    	}
    	//点击自动控制
    	autobut.onclick = function() {
    		autotype = true;
    		if (!gameIsPlay) {//当游戏未开始点击开始按钮才有效
    			clear();
    			h=setInterval(function(){
    				bfs()
    			},1)
    			t = setInterval(function() {
    				moveSnake()
    			}, v)
    			clock();
    			ready();
    		}
    	}
    	//游戏时间
    	function clock() {
    		gameTime = setInterval(function() {
    			s++
    			if (s > 60) {
    				var minutes = Math.floor(s / 60);
    				var sec = s - minutes * 60;
    				times.innerHTML = minutes + "分" + sec + "秒"
    			} else {
    				times.innerHTML = s + "秒"
    			}
    		}, 1000)
    	}
    	//生成随机食物
    	function createfood() {
    		//当页面里有食物,先清除页面上的食物
    		var food = div1.getElementsByTagName("i")[0];//获取食物标签
    		if (food) {//存在食物就移除食物
    			div1.removeChild(food);//移除食物
    		}
    		//生成一个食物
    		var food = document.createElement("i");//一个定义的i标签作为食物
    		x = (Math.round(Math.random() * (maxn-3))+1) * size;//随机生成横纵坐标
    		y = (Math.round(Math.random() * (maxn-3))+1) * size;
    		// console.log("食物位置:"+x+","+y);
    		for(var i=0;i<arr.length;i++){
    			if(x==parseInt(arr[i].style.left)&&y==parseInt(arr[i].style.top)){
    				i=-1;
    				x = (Math.round(Math.random() * (maxn-1))) * size;//随机生成横纵坐标
    				y = (Math.round(Math.random() * (maxn-1))) * size;
    			}
    		}
    		autofoody=x;
    		autofoodx=y;
    		div1.appendChild(food);//添加到div1标签里
    		food.style.left = x + "px";
    		food.style.top = y + "px";
    	}
    	//生成一个新span,添加到蛇尾
    	function addspan() {
    		var span = document.createElement("span");
    		span.style.left = arr[0].style.left;
    		span.style.top = arr[0].style.top;
    		div1.appendChild(span);
    		arr.unshift(span);//将span插入到数组下标为0的位置,unshift() 方法可向数组的开头添加一个或更多元素,其他已存在元素向后移并返回新的长度。
    	}
    
    	//键盘操纵
    	window.onkeydown = function(event) {//获取键盘方向
    		if (event.keyCode == 39 && dir != "left") {
    			dir = "right";
    		}
    		if (event.keyCode == 40 && dir != "top") {
    			dir = "bottom";
    		}
    		if (event.keyCode == 37 && dir != "right") {
    			dir = "left";
    		}
    		if (event.keyCode == 38 && dir != "bottom") {
    			dir = "top";
    		}
    		if (event.keyCode == 13) {//空格为重新开始
    
    			if (!gameIsPlay) {//当游戏结束时才生效
    				clear();
    				t = setInterval(function() {
    					moveSnake()
    				}, speed);
    				clock()
    				ready()
    			}
    		}
    	}
    }
    

    最后来一手项目报告,一手垃圾报告只为完成期末的写的垃圾报告,源码,请移步百度网盘.

    链接:https://pan.baidu.com/s/1S73QdXYZw8BDRMDmQ1BN6w 
    提取码:only 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值