图形化带背景乐的——“贪吃蛇”(用原生js实现)

关于贪吃蛇的实现有很多方法,我选择了使用原生js去实现。游戏的总体思路分为以下几个步骤:
1.利用js动态生成四百个小棋格子,进而组成棋盘;
2.利用随机数,随机的产生黑色小点(我们姑且将它称之为蛇的食物),这里要注意的是,每次对产生的食物做出判断,要是生成的小点他存在于蛇身的内部,就要对它进行重新调用,直到生成一个独立于蛇身外的随即点。
3.接下来就是利用数组来存储蛇的位置,snake[0]为蛇头,snake[snake.length-1]就是蛇尾的位置。
4.然后通过键盘事件,监听蛇要移动的方向,然后进行逻辑移动数组,给蛇头往前走一格,蛇尾的颜色回归棋盘颜色,其它元素依次等于前一个元素,这里要注意越界问题,主要棋盘的个数是从0到399,所以主要逻辑判断
5.我们给他设定循环定时器,当用户选择方向之后,按照时间依次触发函数,朝着指定方向移动,当蛇吃到食物之后,继续触发随机函数产生食物,然后给蛇的尾部加一个,这里还是要注意越界问题
6.在每一次移动之后,调用相应函数,判断蛇头是否撞到了蛇身。

这里只展示js的相关代码,难点部分已标注相关注释,

  • fangxiang用于记录当前蛇的移动方向,用于判断临界问题(比如正在向上移动的蛇,不能突然向下移动…以此之内的)
  • food用于记录产生随机点的位置,用来判断它是不是存在于蛇身
  • socer用于记录当前游戏分值,每吃一个食物就会增加100分,
  • keep用于记录当前创建的定时器,来循环触发方向移动,因为每次改变方向都要清除上一个定时器,否则后累加循环,其次清除定时器的函数只能清除定义的全局变量。
  • snakeColor, qipanColor, speed三个变量分别对应了棋盘颜色,蛇身颜色以及蛇的速度(根据首頁面用户选择的难度不同,进而初始速度不相同,当蛇的长度越来越快,他的速度也会越来越快);

详细的项目代码请前往GitHub下载:下载地址

//初始化蛇数组
var snake = [40,20,0];
//记录当前前进的方向
var fangxiang = 0;
//记录随机点
var food = 20;
//记录分值
var socer = 0;
//全局变量存储定时器
var keep;
//蛇的颜色
var snakeColor = 'red';
//棋盘的颜色
var qipanColor = 'yellow';
//开局的速度
var speed;

//开局调用自执行函数,来生成第一个小点
function main() {
    
    
	//创建400个小元素,id自增加1
    var qipan = document.getElementById("qipan");
		qipan.style.backgroundColor = qipanColor
		for (var i = 0; i < 400; i++) {
    
    
	    //添加 div
			var div = document.createElement("div");
			var id = "id"+i;
			//设置 li 属性,如 id
			div.setAttribute("id", id);
			//增加此元素
			qipan.appendChild(div);
		};
	//生成分数
	document.getElementsByClassName("socer")[0].innerHTML=socer
	//产生随机数并随机产生小点
	change();
	//蛇身颜色渲染
	color();
	//进行向下运动
	keep = setInterval(function(){
    
    direction("s")},speed-snake.length);
	//背景变换色
	bgc()
}
//选择难度
function choose(e){
    
    
	if(e == 1){
    
    
		speed = 300;
	}else if(e == 2){
    
    
		speed = 250
	}else if(e == 3){
    
    
		speed = 200
	}
	//播放背景音乐
	var music = document.getElementById("music")
	music.src = "bgc1.mp3";
	if (music.paused) {
    
     
        music.paused = false;
        music.play(); 
    }
    document.getElementsByClassName("navbar")[0].style.display="none"
    document.getElementsByClassName("choose")[0].style.display="none"
    document.getElementsByClassName("main")[0].style.display="block";
    //调用主要初始化
    main()
}
//蛇的颜色控制
function color(){
    
    
	for(var i = 0;i < snake.length;i++){
    
    
		var id = "id"+snake[i];
		document.getElementById(id).style.backgroundColor=snakeColor
		document.getElementById("id"+snake[0]).innerHTML = "o"
	}
}
//蛇的方向控制
function direction(e){
    
    
	var event = e || "s"
	switch(event){
    
    
		case "w":
			//防止朝相反方向行驶
			if (fangxiang != 2) {
    
    
				var temp = snake[0]
				snake[0] = snake[0]-20;
				//判断越界问题
				if(snake[0] < 0){
    
    
					snake[0] += 400
				}
				//食用果实
				if(food == snake[0]){
    
    
					var tail = snake[snake.length-1]+20
					if(tail < 0){
    
    
						tail += 400
					}
					else if(tail >= 400){
    
    
						tail -= 400
					}
					else if((tail+1)%20 == 0){
    
    
						tail += 20
					}
					else if(tail%20 == 0 && tail > 0){
    
    
						tail -= 20
					}
					snake.push(tail);
					ifmiss(snake[0]);
					document.getElementById("id"+snake[snake.length-1]).style.backgroundColor=snakeColor
					document.getElementById("id"+food).innerHTML = ""
					socer += 100
					document.getElementsByClassName("socer")[0].innerHTML=socer
					change()
				}
				//为头部开辟的新空间赋值颜色
				document.getElementById("id"+snake[0]).style.backgroundColor=snakeColor
				//为尾部走过的旧空间回归原始色
				document.getElementById("id"+snake[snake.length-1]).style.backgroundColor=qipanColor
				//遍历依次移动
				for(var i = snake.length-1;i > 0;i--){
    
    
					if(i == 1){
    
    
						snake[i] = temp;
						break;
					}
					snake[i] = snake[i-1];
				}
				document.getElementById("id"+snake[0]).innerHTML = "o"
				document.getElementById("id"+snake[1]).innerHTML = ""
				ifmiss(snake[0]);
				fangxiang = 1;
				break;
			}
			else{
    
    
				direction("s");
				break;
			}
		case "s":
			//防止朝相反方向行驶
			if (fangxiang != 1) {
    
    
				var temp = snake[0]
				snake[0] = snake[0]+20;
				//判断越界问题
				if(snake[0] >= 400){
    
    
					snake[0] -= 400
				}
				if(food == snake[0]){
    
    
					var tail = snake[snake.length-1]-20
					if(tail < 0){
    
    
						tail += 400
					}
					else if(tail >= 400){
    
    
						tail -= 400
					}
					else if((tail+1)%20 == 0){
    
    
						tail += 20
					}
					else if(tail%20 == 0 && tail > 0){
    
    
						tail -= 20
					}
					snake.push(tail);
					ifmiss(snake[0]);
					document.getElementById("id"+snake[snake.length-1]).style.backgroundColor=snakeColor
					document.getElementById("id"+food).innerHTML = ""
					socer += 100
					document.getElementsByClassName("socer")[0].innerHTML=socer
					change()
				}
				//为头部开辟的新空间赋值颜色
				document.getElementById("id"+snake[0]).style.backgroundColor=snakeColor
				//为尾部走过的旧空间回归原始色
				document.getElementById("id"+snake[snake.length-1]).style.backgroundColor=qipanColor
				//遍历依次移动
				for(var i = snake.length-1;i > 0;i--){
    
    
					if(i == 1){
    
    
						snake[i] = temp;
						break;
					}
					snake[i] = snake[i-1];
				}
				document.getElementById("id"+snake[0]).innerHTML = "o"
				document.getElementById("id"+snake[1]).innerHTML = ""
				ifmiss(snake[0]);
				fangxiang = 2
				break;
			}
			else{
    
    
				direction("w");
				break;
			}
		case "a":
			//防止朝相反方向行驶
			if (fangxiang != 4) {
    
    
				var temp = snake[0]
				snake[0] -= 1
				//判断越界问题
				if((snake[0]+1)%20 == 0){
    
    
					snake[0] += 20
				}
				if(food == snake[0]){
    
    
					var tail = snake[snake.length-1]+1
					if(tail < 0){
    
    
						tail += 400
					}
					else if(tail >= 400){
    
    
						tail -= 400
					}
					else if((tail+1)%20 == 0){
    
    
						tail += 20
					}
					else if(tail%20 == 0 && tail > 0){
    
    
						tail -= 20
					}
					snake.push(tail);
					ifmiss(snake[0]);
					document.getElementById("id"+snake[snake.length-1]).style.backgroundColor=snakeColor
					document.getElementById("id"+food).innerHTML = ""
					socer += 100
					document.getElementsByClassName("socer")[0].innerHTML=socer
					change()
				}
				//为头部开辟的新空间赋值颜色
				document.getElementById("id"+snake[0]).style.backgroundColor=snakeColor
				//为尾部走过的旧空间回归原始色
				document.getElementById("id"+snake[snake.length-1]).style.backgroundColor=qipanColor
				//遍历依次移动
				for(var i = snake.length-1;i > 0;i--){
    
    
					if(i == 1){
    
    
						snake[i] = temp;
						break;
					}
					snake[i] = snake[i-1];
				}
				document.getElementById("id"+snake[0]).innerHTML = "o"
				document.getElementById("id"+snake[1]).innerHTML = ""
				ifmiss(snake[0]);
				fangxiang = 3
				break;
			}
			else{
    
    
				direction("d");
				break;
			}
		case "d":
			//防止朝相反方向行驶
			if (fangxiang != 3) {
    
    
				var temp = snake[0]
				snake[0] = snake[0]+1;
				//判断越界问题
				if(snake[0]%20 == 0  && snake[0] > 0){
    
    
					snake[0] -= 20
				}
				if(food == snake[0]){
    
    
					var tail = snake[snake.length-1]-1
					if(tail < 0){
    
    
						tail += 400
					}
					else if(tail >= 400){
    
    
						tail -= 400
					}
					else if((tail+1)%20 == 0){
    
    
						tail += 20
					}
					else if(tail%20 == 0 && tail > 0){
    
    
						tail -= 20
					}
					snake.push(tail);
					ifmiss(snake[0]);	
					document.getElementById("id"+snake[snake.length-1]).style.backgroundColor=snakeColor
					document.getElementById("id"+food).innerHTML = ""
					socer += 100
					document.getElementsByClassName("socer")[0].innerHTML=socer
					change()
				}
				//为头部开辟的新空间赋值颜色
				document.getElementById("id"+snake[0]).style.backgroundColor=snakeColor
				//为尾部走过的旧空间回归原始色
				document.getElementById("id"+snake[snake.length-1]).style.backgroundColor=qipanColor
				//遍历依次移动
				for(var i = snake.length-1;i > 0;i--){
    
    
					if(i == 1){
    
    
						snake[i] = temp;
						break;
					}
					snake[i] = snake[i-1];
				}
				document.getElementById("id"+snake[0]).innerHTML = "o"
				document.getElementById("id"+snake[1]).innerHTML = ""
				fangxiang = 4;
				break;
			}
			else{
    
    
				direction("a");
				break;
			}
		case "p":
				clearInterval(keep);
				break;
		default:
			switch(fangxiang){
    
    
				case 1:
					window.clearInterval(keep)
					keep = setInterval(function(){
    
    direction("w")},speed-snake.length);
					break;
				case 2:
					window.clearInterval(keep)
					keep = setInterval(function(){
    
    direction("s")},speed-snake.length);
					break;
				case 3:
					window.clearInterval(keep)
					keep = setInterval(function(){
    
    direction("a")},speed-snake.length);
					break;
				case 4:
					window.clearInterval(keep)
					keep = setInterval(function(){
    
    direction("d")},speed-snake.length);
					break;
			}
	}
}
//判断是否撞到自身
function ifmiss(head){
    
    
	if (snake[0] == snake[snake.length]+1) {
    
    
			miss();
	}
	else if(snake[0] == snake[snake.length]-1){
    
    
			console.log(snake)
			miss();
	}
	else if(snake[0] == snake[snake.length]-20){
    
    
			miss();
	}
	else if(snake[0] == snake[snake.length]+20){
    
    
			miss();
	}
	for (var i = 1; i < snake.length; i++) {
    
    
		if (head == snake[i]) {
    
    
			miss();
			return;
		};
	}
}
//当撞上之后
function miss(){
    
    
	document.getElementsByClassName("end")[0].style.display="block"
	document.getElementsByClassName("endSocer")[0].innerHTML="得分:"+socer;
	document.getElementById("id"+snake[0]).innerHTML = ""
	for(var i = 0;i < snake.length;i++){
    
    
		document.getElementById("id"+snake[i]).style.backgroundColor=qipanColor
	}
	window.clearInterval(keep)
}
//点击确定重新开始
function newgame(){
    
    
	document.getElementsByClassName("end")[0].style.display="none";
	socer = 0;
	fangxiang = 2;
	snake = [40,20,0];
	keep = setInterval(function(){
    
    direction("s")},speed-snake.length);
	document.getElementsByClassName("socer")[0].innerHTML=socer
	color();
}
//直线行驶
var dir = document.getElementById("body");
dir.onkeydown = line;
var key
function line(event){
    
    
	if (key == event.key) return;
	    key = event.key;
	window.clearInterval(keep)
	keep = setInterval(function(){
    
    direction(key)},speed-snake.length);
}
//产生随机小点函数
function change(){
    
    
	var temp = Math.round(Math.random()*399);
	for(var i = 0;i < snake.length;i++){
    
    
		if (temp == snake[i]) {
    
    
			console.log(temp);
			document.getElementById("id"+temp).innerHTML = "";
			change();
			return;
		};
	}
	var id = "id"+temp

		food = temp
	var flag = document.getElementById(id);
	flag.innerHTML = "*";
}
//背景颜色
function bgc(){
    
    
	setInterval(function(){
    
    
		var a = Math.round(Math.random()*255);
		var b = Math.round(Math.random()*255);
		var c = Math.round(Math.random()*255);
		document.getElementById("body").style.backgroundColor="rgb("+a+","+b+","+c+")"
	},3000);
}

猜你喜欢

转载自blog.csdn.net/baldicoot_/article/details/108019666