快到期末了也是老师喊写一个js贪吃蛇报告.所以就写了下,下面分享出来.
直接上代码了,除了自动寻找食物的bfs没有注释,其它注释都挺全的.这个只是简单的实现了,并没有很好的优化.后面有报告及源码,直接运行即可成功.
- 先来把截图
- 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>
- 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; }
- 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