JS实现贪吃蛇小游戏(详细注释)

小游戏目录结构
项目结构
游戏运行效果图
在这里插入图片描述HTML代码
css代码
js代码


<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<style media="screen">
			*{
				margin: 0;
				padding: 0;
			}
			.wrap{
				width: 600px;
				margin: 0 auto;
				position: relative;
			}
			p{
				position: absolute;
				left: 65%;
				top: 10%;
			}
			h1{
				text-align: center;
				margin-bottom: 20px;
			}
			#score{
				text-align: center;
				font-size: 20px;
			}
			#snake_map{
				margin: 0 auto;
				border: 1px solid skyblue;
			}
			.row{
				height: 20px;
			}
			.col{
				height: 20px;
				width: 20px;
				box-sizing: border-box;
				border: 1px solid lightgray;
				background: rgb(250,250,250);
				float: left;
			}
			.activeSnake{
				background: black;
			}
			.egg{
				background: red;
			}
			#Pause{
				margin-left:18%;
				border: 1px solid skyblue;
				color: white;
				background: skyblue;
				width: 50px;
				height: 30px;
				margin-bottom: 10px;
				border-radius: 5px;
			}
			#Start,#Refresh,#Speed{
				border: 1px solid skyblue;
				background: skyblue;
				width: 50px;
				height: 30px;
				border-radius: 5px;
				margin-left: 15px;
			}

		</style>
	</head>
	<body>
		<div class="wrap">
			<h1>贪吃蛇游戏</h1>
			<p style="font-size: 20px;color: red;">
				得分:<span id="score" style="color: black;">0</span>
			</p>
			<input id="Pause" type="button" name="name" value="暂停" />
			<input id="Start" type="button" name="name" value="开始" />
			<input id="Refresh" type="button" name="name" value="重开" />
			<input id="Speed" type="button" name="name" value="等级" />
			<div id="snake_map"></div><!-- 25行  20列-->
		</div>
		<script type="text/javascript">
			var score=document.getElementById('score');//获取分数id
			var map=document.getElementById('snake_map');//获取路径地图id
			var rowNumber=25;//行数
			var columnNumber=20;//列数
			var mapWidth=columnNumber*20+'px';//地图宽
			var mapHeight=rowNumber*20+'px';//地图高
			map.style.width=mapWidth;
			map.style.height=mapHeight;//设置地图宽高
			var snakeDIVPosition=[];//创建一个二维数组,用来记录地图的所有div的位置
			for(var i=0;i<rowNumber;i++){//通过双层for循环创建地图元素
				var rowDIV=document.createElement('div');//创建div
				rowDIV.className='row';//设置div样式
				map.appendChild(rowDIV);//将行div添加到路径地图map中
				var rowArray=[];
				for(var j=0;j<columnNumber;j++){
					//创建每一行中的方块div
					var columnDIV=document.createElement('div');
					//设置css样式
					columnDIV.className='col';
					//将方块div添加到路径地图的map中
					rowDIV.appendChild(columnDIV);
					//创建一个行级数组,用来存储当前行中的每个方块div
					rowArray.push(columnDIV);
				}
				snakeDIVPosition.push(rowArray);
			}
			var snake=[];
			for(var i=0;i<3;i++){
				snakeDIVPosition[0][i].className='col activeSnake';
				snake[i]=snakeDIVPosition[0][i];
			}
			var x=2;
			var y=0;
			var scoreCount=0;
			var eggX=0;
			var eggY=0;
			var direction='right';
			var changeDir=true;
			var delayTimer=null;
			document.onkeydown=function(e){
				if(!changeDir){
					return;
				}
				e=e||window.e;
				if(direction=='right' && e.keyCode==37){
					return;
				}
				if(direction=='left'  && e.keyCode==39){
					return;
				}
				if(direction=='up'  && e.keyCode==40){
					return;
				}
				if(direction=='down'  && e.keyCode==38){
					return;
				}
				switch (e.keyCode){
					case 37:
					direction='left';
					break;
					case 38:
					direction='up';
					break;
					case 39:
					direction='right';
					break;
					case 40:
					direction='down';
					break;
				}
				changeDir=false;
				delayTimer =setTimeout(function(){
					changeDir=true;
					
				},300);
			}
			/*
			 
			 * 
			 * */
			function snakeMove(){
				switch(direction){
					case 'left':
					x--;
					break;
					case 'right':
					x++;
					break;
					case 'up':
					y--;
					break;
					case 'down':
					y++;
					break;
					
				}
				if(x<0||y<0|| x>=columnNumber||y>=rowNumber){
					alert('Game Over!!!');
					clearInterval(moveTimer);
					return;
				}
				for(var i=0;i<snake.length;i++){
					if(snake[i]==snakeDIVPosition[y][x]){
						alert('Game Over!!!');
						clearInterval(moveTimer);
						return;
					}
				}
				
				/*
				 
				 * */
				if(eggX==x && eggY==y){
					snakeDIVPosition[eggY][eggX].className='col activeSnake';
					snake.push(snakeDIVPosition[eggY][eggX]);
					scoreCount++;
					score.innerHTML=scoreCount;
					createNewEgg();
				}else{
					snake[0].className='col';
					snake.shift();
					snakeDIVPosition[y][x].className='col activeSnake';
					snake.push(snakeDIVPosition[y][x]);
				}
			}
			var moveTimer=setInterval('snakeMove()',300);
			function random(min,max){
				return Math.floor(Math.random()*(max-min+1)+min);
			}
			function createNewEgg(){
				eggX=random(0,columnNumber-1);
				eggY=random(0,rowNumber-1);
			
			if(snakeDIVPosition[eggY][eggX].className=='col activeSnake'){
				createNewEgg();
			}else{
				snakeDIVPosition[eggY][eggX].className='col egg';
			}
			}
			
			createNewEgg();
			var pause=document.getElementById('Pause');
			var start=document.getElementById('Start');
			var refresh=document.getElementById('Refresh');
			var speed=document.getElementById('Speed');
			pause.onclick=function(){
			clearInterval(moveTimer);
			}
			start.onclick=function(){
			clearInterval(moveTimer);
			moveTimer=setInterval('snakeMove()',speed1);
			}	
			refresh.onclick=function(){
				window.location.reload();
			}
			var speed1=300;
			speed.onclick=function(){
			speed1-=20;
			clearInterval(moveTimer);
			moveTimer=setInterval('snakeMove()',speed1);
			}
			
		</script>
	</body>
</html>


*{ 
	padding:0; margin:0;
}
html,body{ 
	width:100%; 
	height:100%;
	}
body{ 
		position:relative;
		}
div#container{ 
	position:absolute; 
	top:0; 
	bottom:0;
	 left:0; 
	 right:0;
	  margin:auto; 
	  width:800px;
	   height:500px;
	    border:1px solid black; 
	    font-size:0px;
	 }
	span{ 
	 	display:inline-block; 
	 	border:1px solid black;
	 	 box-sizing:border-box;
	 	 }
	span.snake{ 
	 	 	position:absolute; 
	 	 	background-color:red;
	 	 	}
	span.food{ 
		position:absolute; 
		background-color:blue;
		}

var box={width:50,height:50};//每一个方块的高度
var snake=[];//保存蛇每一节身体对应的span
var DIR={ 
	DIR_RIGHT:1, 
	DIR_LEFT:2, 
	DIR_TOP:3, 
	DIR_BOTTOM:4
		};
		var dir=DIR.DIR_BOTTOM;
		var food=null; //始终记录当前的食物 
		window.onload=function(){ 
			//1.初始化地图 
			initMap();
			//2.创建蛇 
			//2.5随机显示食物 
			showFood(); 
			createSnake(); 
			//3.让蛇动起来 
			setInterval(snakeMove,100); 
			//4.控制蛇移动
			document.onkeyup=function(e){
			switch(e.keyCode){  
			case 37:dir=DIR.DIR_LEFT;break; 
			case 38:dir=DIR.DIR_TOP;break; 
			case 39:dir=DIR.DIR_RIGHT;break; 
			case 40:dir=DIR.DIR_BOTTOM;break;  
			} 
			}
			};
			function isInSnakeBody(left,top){ 
				for(var i=0;i<snake.length;i++){ 
					if(snake[i].offsetTop==top&&snake[i].offsetLeft==left){
					return true; 
					} 
				}
				}
			//这种随机生成食物的方法效率低---随着蛇身体的增长,随机生成食物的时间会变慢。
			function showFood(){ 
				var con=document.getElementById("container"); 
				food=document.createElement("span"); 
				food.className="food"; 
				food.style.width=box.width+"px";
				food.style.height=box.height+"px"; 
				var left,top; 
				do{ 
					left=Math.floor((con.offsetWidth-2)/box.width*Math.random())*box.width; 
					top=Math.floor((con.offsetHeight-2)/box.height*Math.random())*box.height; 
				}while(isInSnakeBody(left,top)); 
				food.style.left=left+"px"; 
				food.style.top=top+"px"; 
				con.appendChild(food);
			}
			function initMap(){ 
				var con=document.getElementById("container"); 
				var row=Math.floor(con.offsetWidth/box.width); 
				var rol=Math.floor(con.offsetHeight/box.height); 
				var num=row*rol; 
				var newSpan=null;
				for(var i=1;i<=num;i++){ 
					newSpan=document.createElement("span"); 
					newSpan.style.width=box.width+"px"; 
					newSpan.style.height=box.height+"px"; 
					con.appendChild(newSpan); 
				} 
			}
			function createSnake(){ 
				var newBody=null; 
				var con=document.getElementById("container"); 
				for(var i=1;i<=5;i++){ 
					newBody=document.createElement("span"); 
					newBody.style.width=box.width+"px"; 
					newBody.style.height=box.height+"px"; 
					newBody.style.left=(i-1)*box.width+"px"; 
					newBody.style.top="0px"; 
					newBody.className="snake"; 
					con.appendChild(newBody); 
					snake.push(newBody); 
				}
				}
			function snakeMove(){ 
				var con=document.getElementById("container"); 
				//蛇头移动 
				var head=snake[snake.length-1];
				var newTop=head.offsetTop,newLeft=head.offsetLeft;
				switch(dir){ 
				case DIR.DIR_LEFT:newLeft-=box.width; break; 
				case DIR.DIR_RIGHT:newLeft+=box.width; break; 
				case DIR.DIR_TOP:newTop-=box.height; break; 
				case DIR.DIR_BOTTOM:newTop+=box.height; break;
				default:break; 
				} 
				//如果超出边界,计算蛇头下一个位置的坐标 
				if(newLeft>con.offsetWidth-2-1){newLeft=0;} 
				if(newLeft<0){newLeft=con.offsetWidth-2-box.width;} 
				if(newTop<0){newTop=con.offsetHeight-2-box.height;} 
				if(newTop>con.offsetHeight-2-1){newTop=0;} 
				//判断新蛇头的位置是不是在蛇身体里面 
				//for(var i=0;i<snake.length-1;i++){ 
					// if(snake[i].offsetLeft==newLeft&&snake[i].offsetTop==newTop){ 
						// alert("Game over!!"); 
						// window.location.href=window.location.href; 
					// }  
				//} 
				//1.如果吃到食物 
				if(newLeft==food.offsetLeft&&newTop==food.offsetTop){ 
					food.className="snake"; 
					snake.push(food); 
					showFood(); 
					return;
				} 
				//2.如果没吃到 
				//除蛇头外身体移动 
				for(var i=0;i<snake.length-1;i++){ 
					snake[i].style.top=snake[i+1].offsetTop+"px"; 
					snake[i].style.left=snake[i+1].offsetLeft+"px"; 
				} 
				head.style.left=newLeft+"px"; 
				head.style.top=newTop=newTop+"px";
			}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
游戏说明:<br>一个5*5的方格 打算往每个格子里放房子,有4种颜色的房子 <br>蓝色的房子 占10人口 随便放在哪里都行 <br>红色的房子 占20人口 要求和蓝色的房子相邻 <br>绿色的房子 占30人口 要求和蓝色,红色的房子相邻 <br>黄色的房子 占40人口 要求和蓝色,红色,绿色的房子相邻 <br>问 如何放置 才能使5*5的格子占用的人口数量最大?<br><br>操作说明:<br>拉动各颜色的房子到欲放置的格子处释放鼠标,如果格子符合该颜色房子的需求则房子成功放入,否则房子不放入,如:欲放黄色房子,则本格子上下左右需存在蓝绿红三种房子。 <br>单击任何一个格子弹出该格子当前可放入的房子选项,双击房子即可放入,或者选中其中一个后按回车或点选择亦可放入。 <br>双击有房子的格子或房子即可拆掉此房子。 <br>键盘操作: <br>按上下左右箭头可在表格内移动,当前格子背景色为黑色,如无选中则从第一行第一列开始,按回车后选择房子,按Delete或“.”为拆掉房子。 <br>如果弹出选择房子时,上下左右箭头为选择当前格子可用的房子(如:向放黄色房子需先在需要放置的格子上下左右格放好蓝绿红房子,方可选择),按下回车后此房子加入格子内,Esc键为不做选择并关掉选择房子。 <br>如果拆除房子的邻居有对本房子要求时本房子不可拆除,需先拆除对于本房子做要求的房子,如:想拆掉蓝色房子,但上下左右有红色房子则需先拆掉红色房子方可拆掉蓝色房子。 <br>按Ctrl+Z可后退一步,如果后退后未再做操作按Ctrl+Y可前进一步,可多次后退或前进(在房子总数足够或后退步数足够的情况下),反之后退前进无效。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值