刚看完关于js的视频,迫不急待的想试验下成果,所以试写了下贪吃蛇的效果:
上面就是我写的一个简易的贪吃蛇截图,红色的为蛇头—.—。。。。
下面来记录下我的代码过程
html代码
首先先附上js代码中的打包函数
function getStyle(elem,prop){ //elem是元素,prop是元素的属性,这表示从我需要的元素中提取出我需要的属性,打包在函数里是因为需要解决兼容性问题
if(window.getComputedStyle){
return window.getComputedStyle(elem,null)[prop];
}else{
return elem.currentStyle[prop];
}
}
function bg3(){ //给我的贪吃蛇的食物添加随机颜色
var r=Math.floor(Math.random()*256);
var g=Math.floor(Math.random()*256);
var b=Math.floor(Math.random()*256);
return "rgb("+r+','+g+','+b+")";//所有方法的拼接都可以用ES6新特性`其他字符串{$变量名}`替换
}
function lt(){ //食物的随机左右位置
return Math.floor(Math.random()*20) * 30 + 'px' ;
}
function tp(){ //食物的随机上下位置
return Math.floor(Math.random()*10) * 30 + 'px';
}
function tt(){ //组织随机食物的特性
var div9 = document.createElement('div');
document.body.appendChild(div9);
div9.style.width = 30 + 'px';
div9.style.height = 30 + 'px';
div9.style.backgroundColor = bg3();
div9.style.position = 'absolute';
div9.style.left = lt() ;
div9.style.top = tp() ;
}
//d1表示的是对蛇头的移动位置的封装
function d1(elem,keyCode){ //elem表示元素,keyCode的表示传过来对应键盘按键的数字
if(keyCode == 37){ //37表示键盘的左键
elem.style.left = parseInt(getStyle(elem,'left')) - 30 + "px" ; //表示向左移30px
}else if(keyCode == 38){ //38表示键盘的上键
elem.style.top = parseInt(getStyle(elem,'top')) - 30 + "px" ; //表示向上移30px
}else if(keyCode == 39){ //39表示键盘的右键
elem.style.left = parseInt(getStyle(elem,'left')) + 30 + "px" ; //表示向右移30px
}else if(keyCode == 40){ //40表示键盘的下键
elem.style.top = parseInt(getStyle(elem,'top')) + 30 + "px" ; //表示向下移30px
}
}
//d2表示的是第一个食物被吃后变成蛇身的首次位置移动
function d2(elem,keyCode){ //elem表示元素,keyCode的表示传过来对应键盘按键的数字
if(keyCode == 38){
elem.style.top = parseInt(getStyle(elem.previousElementSibling,'top')) + 30 + "px";
elem.style.left = elem.previousElementSibling.style.left;
}else if(keyCode == 37){
elem.style.left = parseInt(getStyle(elem.previousElementSibling,'left')) + 30 + "px";
elem.style.top = elem.previousElementSibling.style.top;
}else if(keyCode == 40){
elem.style.top = parseInt(getStyle(elem.previousElementSibling,'top')) - 30 + "px" ;
elem.style.left = elem.previousElementSibling.style.left;
}else if(keyCode == 39){
elem.style.left = parseInt(getStyle(elem.previousElementSibling,'left')) - 30 + "px";
elem.style.top = elem.previousElementSibling.style.top;
}
}
//d3是为了简化代码而写的封装函数,表示的是当第一个食物被吃后,食物变成蛇身,跟着蛇头运动
function d3(n,elem,keyCode){
for(n ;n>1;n--){
var div3 = document.getElementsByTagName('div')[n];//从下面传上来一个表示被吃食物的元素
if(keyCode == 37){ //左键
div3.style.left = parseInt(getStyle(elem,'left')) + "px" ;//食物的左右运动情况
div3.style.top = elem.style.top ;//当按了左键,蛇身(/食物)的上下和蛇头要保持一致
}else if(keyCode == 38){ //上键
div3.style.top = parseInt(getStyle(elem,'top')) + "px" ;//食物的左右运动情况
div3.style.left = elem.style.left ;;//当按了上键,蛇身(/食物)的左右和蛇头要保持一致
}else if(keyCode == 39){ //右键
div3.style.left = parseInt(getStyle(elem,'left')) + "px" ;//食物的左右运动情况
div3.style.top = elem.style.top ;;//当按了右键,蛇身(/食物)的上下和蛇头要保持一致
}else if(keyCode == 40){ //下键
div3.style.top = parseInt(getStyle(elem,'top')) + "px" ;//食物的左右运动情况
div3.style.left = elem.style.left ;;//当按了下键,蛇身(/食物)的左右和蛇头要保持一致
}
}
}
//d4也是为了代码简洁而封装的,表示的是第二个食物及之后的食物的运动情况
function d4(n,keyCode){
for(n ;n>2;n--){
var div3 = document.getElementsByTagName('div')[n];
if(keyCode == 37){
div3.style.left = parseInt(getStyle(div3.previousElementSibling,'left')) + "px" ;
div3.style.top = div3.previousElementSibling.style.top ;
}else if(keyCode == 38){
div3.style.top = parseInt(getStyle(div3.previousElementSibling,'top')) + "px" ;
div3.style.left = div3.previousElementSibling.style.left ;
}else if(keyCode == 39){
div3.style.left = parseInt(getStyle(div3.previousElementSibling,'left')) + "px" ;
div3.style.top = div3.previousElementSibling.style.top ;
}else if(keyCode == 40){
div3.style.top = parseInt(getStyle(div3.previousElementSibling,'top')) + "px" ;
div3.style.left = div3.previousElementSibling.style.left ;
}
}
}
//上面的div3.previousElementSibling.style.left ;表示的是div3元素的前一个位置的元素(previousElementSibling)的左边(left)位置的取值,top同理
下面是js的主体部分
var a = new Array(true,true,true); //充当下面的启动开关数组
var div1 = document.getElementsByTagName('div')[0];//获取表示蛇头的元素
var div2 = document.getElementsByTagName('div')[1];//获取表示第一个食物的元素
//为第一个食物设置随机位置随机颜色,以及固定大小
div2.style.width = 30 + 'px';
div2.style.height = 30 + 'px';
div2.style.backgroundColor = 'green';
div2.style.position = 'absolute';
div2.style.left = lt() ; //调用上述的lt函数
div2.style.top = tp() ; //调用上述的tp函数
var timer; //用来抓取每隔时间的变化
window.onkeydown = function(e){ //当在window下触发键盘按键时发生的事件
clearInterval(timer); //用来清除每次按键触发的时间变换效果
if(a[0] == true){ //当开关1为true是触发的时间
timer = setInterval(function(){ //timer抓住每隔时间的变化
if(parseInt(div1.style.left) == parseInt(div2.style.left) && parseInt(div1.style.top) == parseInt(div2.style.top)){ //当蛇头的左边位置和上边位置与第一个食物的左右上下位置相等时,触发下面事件,,,就是蛇吃到食物时
d1(div1,e.keyCode); //返回给d1函数(div1(蛇头)元素,以及触发键盘的按键数字)
tt(); //触发tt()函数,创建下一个随机食物
a[0] = false; //开关1等于false,关掉这个事件
a[1] = true; //开关2等于true,开始另一个事件
}else{ //没有满足上述的if条件时,执行下面的语句
d1(div1,e.keyCode); //触发d1函数,表示蛇头的变动
}
},150); //设置了每个150ms变动一次上述的情况,使蛇头能够自动移动
}else if(a[0] == false){ //开关1关闭后,执行下面的事件
if(a[1] == true){ //开关2开启
timer = setInterval(function(){ //timer抓住每隔时间的变化
if(parseInt(div1.style.left) == parseInt(div2.nextElementSibling.nextElementSibling.style.left) && parseInt(div1.style.top) == parseInt(div2.nextElementSibling.nextElementSibling.style.top)){ //蛇头吃到第n个食物时(具体解释看上面的if条件说明,基本与上述雷同),注:这里的nextElementSibling表示的是这个元素(div2)的下一个元素,两个nextElementSibling表示下一个的下一个元素
d1(div1,e.keyCode);
d2(div2,e.keyCode);
tt();
a[1] = false;
a[2] = true;
}
else{
d1(div1,e.keyCode);
d2(div2,e.keyCode);
}
},150);
}else if(a[1] == false){
if(a[2] == true){
timer = setInterval(function(){
if(parseInt(div1.style.left) == parseInt(div2.nextElementSibling.nextElementSibling.nextElementSibling.style.left) && parseInt(div1.style.top) == parseInt(div2.nextElementSibling.nextElementSibling.nextElementSibling.style.top)){ //与上述的if解释差不多,不明白请往上看if的解释
d1(div1,e.keyCode);
d3(2,div2,e.keyCode);
d2(div2,e.keyCode);
tt();
a[2] = false;
a[3] = true;
}else{
d1(div1,e.keyCode);
d3(2,div2,e.keyCode);
d2(div2,e.keyCode);
}
},150);
}else if(a[2] == false){
if(a[3] == true){
timer = setInterval(function(){
if(parseInt(div1.style.left) == parseInt(document.getElementsByTagName('div')[4].style.left) && parseInt(div1.style.top) == parseInt(document.getElementsByTagName('div')[4].style.top)){ //与上述的if解释差不多,不明白请往上看if的解释
d1(div1,e.keyCode);
d4(3,e.keyCode);
d3(2,div2,e.keyCode);
d2(div2,e.keyCode);
tt();
a[3] = false;
a[4] = true;
}else {
d1(div1,e.keyCode);
d4(3,e.keyCode);
d3(2,div2,e.keyCode);
d2(div2,e.keyCode);
}
},150);
}else if(a[3] == false){
if(a[4] == true){
timer = setInterval(function(){
if(parseInt(div1.style.left) == parseInt(document.getElementsByTagName('div')[5].style.left) && parseInt(div1.style.top) == parseInt(document.getElementsByTagName('div')[5].style.top)){ //与上述的if解释差不多,不明白请往上看if的解释
d1(div1,e.keyCode);
d4(4,e.keyCode);
d3(2,div2,e.keyCode);
d2(div2,e.keyCode);
tt();
a[4] = false;
a[5] = true;
}else{
d1(div1,e.keyCode);
d4(4,e.keyCode);
d3(2,div2,e.keyCode);
d2(div2,e.keyCode);
}
},150);
}else if(a[4] == false){
timer = setInterval(function(){
d1(div1,e.keyCode);
d4(5,e.keyCode);
d3(2,div2,e.keyCode);
d2(div2,e.keyCode);
},150);
}
}
}
}
}
}
window.onkeyup = function(){ //当按键松开是触发的事件
if( parseInt(div1.style.left) < 0 || parseInt(div1.style.top) < 0 ||parseInt(div1.style.left) > 600||parseInt(div1.style.top) > 600){ //给蛇头制定了一个运动范围,当超出范围会触发警告窗口
alert('你输了');
clearInterval(timer);//清除所有每隔150ms的运动状态
}
}
上述就是全部的贪吃蛇代码,写的不是很理想:
致命问题是,上述代码只实现了贪吃蛇只能吃六个食物,之后的食物无法吃,也就是我暂时想不到什么方法可以将上述的if/else if不断的触发生成另一个if/else if,然后再生成另一个if/else if,现阶段如果想加食物,就不得不在主js代码后再加上段if/else if和开关,才能使蛇吃到下一个食物。
如果哪位大佬会的话,请留下你珍贵的解决方案,在下感激不尽!!!当然也欢迎和我一样的技术白来这留下疑问,或者愿意的一起交流,加Q281668672