使用JavaScript实现简单的小游戏-贪吃蛇

最近初学JavaScript,在这里分享贪吃蛇小游戏的实现过程, 希望能看到的前辈们能指出这个程序的不足之处。
##大致思路
- 首先要解决的问题 - 随着蛇头的前进,尾巴也要前进。 - 用键盘控制蛇的运动方向。 - 初始化食物的时候不能初始化到蛇的身体上。 - 蛇吃食物的时候身体会变长。 - 蛇头碰到“墙”,或者自己的身体游戏结束 - 不影响游戏的实现但是有关于游戏体验的设计 - 界面的美观。 - 分数的设置。 - 等级的设置(随着分数的增加,蛇前进的速度的增加)。 - 暂停与继续的快捷键。

##符号$说明
function $(id){       //在文件base.js中
	return document.getElementById(id);
}


##代码
<!DOCTYPE html>
<html>
	<head>
		<title>Snake</title>
		<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
		<style type="text/css" >
		body{background-color: #eee; font-family: 手札体-简;}
			#page{ 960px; height: 560px; margin: 30px auto; background-color: #fdf5e6;box-shadow: 3px 3px 3px rgba(0,0,0,0.2),10px 10px 20px rgba(0,0,0,0.2); border-radius: 5px;}
			#page div{float: left;}
			#left{ 710px; height: 560px; }
			table{margin: 20px 100px;background-color: #9cc;}
			td{background-color: #cff;}

			#right{ 205px; height: 560px;}
			#right div{float: none;}
			#score{ 200px; height: 190px;;background-color: #ffffe0; border-radius: 10px;box-shadow: 3px 3px 3px rgba(0,0,0,0.2),5px 5px 10px rgba(0,0,0,0.2);margin-top: 20px;}
			#rank{ 200px; height: 190px; margin-top: 10px;background-color: #ffffe0;border-radius: 10px;box-shadow: 3px 3px 3px rgba(0,0,0,0.2),5px 5px 10px rgba(0,0,0,0.2);}
			
			#right .tag{height:30px;  200px ;font-size: 40px;color: #9cf;font-weight: bolder; }
			#score_num{height: 130px;  200px; text-align: center;color: #9cf; font-size: 100px;}
			#rank_num{height: 130px;  200px; text-align: center;color: #9cf; font-size: 100px;}
			#notice{ 200px;color: #9cf; margin-top: 5px;box-shadow: 3px 3px 3px rgba(0,0,0,0.2),5px 5px 10px rgba(0,0,0,0.2);background-color: #ffffe0; border-radius: 5px;margin-top: 90px;}
		</style>
		<script type="text/javascript" src="base.js"></script>
		<script type="text/javascript">
			//全局变量
			var max_scope = 30;//贪吃蛇的移动范围
			var unit = 13;//每一个单元格的大小
			var speed = 300;//贪吃蛇移动速度
			var direction = 'left';//贪吃蛇移动方向
			var snake_body = null;
			var interval = null;//计时器
			var food = null;
			var score = 0;//分数(每吃一次,分数加一)
			var rank = 1;//随着分数的增加,等级逐渐增加,速度逐渐增加
			

			//初始化游戏,使用表格做贪吃蛇移动的范围
			function initGame(){
				snake_body = new Array();

				for(i = 0 ; i < max_scope; i++)
				{
					var row = document.createElement("tr");
					for( j = 0 ; j < max_scope; j++)
					{
						var cell = document.createElement("td");
						cell.id = i + "-" + j;
						cell.width = unit;
						cell.height = unit;
						row.appendChild(cell);
					}
					$("tbody").appendChild(row);
				}
				initSnake();
				snakeInterval();
				initFood();
			}


			//贪吃蛇身体初始化(随机生成)
			function initSnake(){
				var x = parseInt(Math.random()*(max_scope-2));
				var y = parseInt(Math.random()*(max_scope-2));
				var now_position = x + "-" + y;
				snake_body.push(now_position);

				setCellState(now_position);


			}

			// 贪吃蛇身体染色
			function setCellState(id){
				$(id).style.background = "#000";
			}

			// 食物染色
			function setFootState(id){
				$(id).style.background = "#b10000";
			}

			// 贪吃蛇尾巴离开位置染色
			function setCellStateBack(id){
				$(id).style.background = "";
			}

			// 获取贪吃蛇坐标
			function getSnakePos(i){
				switch(i){
					case 'x':
					return snake_body[0].split('-')[0];
					case 'y':
					return snake_body[0].split('-')[1];
				}

			}

			// 计时器
			function snakeInterval(){
				
				interval = window.setInterval('snakeMove()',speed);

			}

			// 初始化计时器
			function resetSnakeInterval(){
				window.clearInterval(interval);
				interval = window.setInterval('snakeMove()',speed);
			}

			// 设置蛇的移动与移动过程中发生的事件
			function snakeMove(){

				foodx = food.split('-')[0];
				foody = food.split('-')[1];

				switch(direction){

					case 'left':
					_x = getSnakePos('x');
					_y = parseInt(getSnakePos('y')) -1;
					break;
					case 'right':
					_x = getSnakePos('x');
					_y = parseInt(getSnakePos('y')) +1;
					break;

					case 'up':
					_x = parseInt(getSnakePos('x')) -1;
					_y = getSnakePos('y');
					break;
					case 'down':
					_x = parseInt(getSnakePos('x')) +1;
					_y = getSnakePos('y');
					break;
					default:
					_x = getSnakePos('x');
					_y = parseInt(getSnakePos('y')) -1;
					break;
				}

				//撞到墙游戏结束
				if (_x < 0 || _x >= max_scope|| _y < 0 || _y >= max_scope){
					alert("Game Over! Stupid!");
					window.clearInterval(interval);
				}

				//撞到自己游戏结束
				else if (eatItself(_x, _y))
				{
					alert("Game Over! Stupid!");
					window.clearInterval(interval);
				}
				
				//蛇吃到食物与吃到食物以后加一分,并设置相应的等级
				else if (foodx == _x && foody == _y)
				{
					snake_body.unshift(foodx + '-' + foody);
					setCellState(snake_body[0]);
					initFood();
					score+=1;
					$('score_num').innerText = score;
					if (score == 3) {
						speed = 250; 
						resetSnakeInterval();
						rank = 2;
					}
					if (score == 6) {
						speed = 200; 
						resetSnakeInterval();
						rank = 3;
					}
					if (score == 10) {
						speed = 150; 
						resetSnakeInterval();
						rank = 4;
					}
					if (score == 20) {
						speed = 100;
						resetSnakeInterval();
						 rank = 5;
					}
					if (score == 30) {
						speed = 70; 
						resetSnakeInterval();
						rank = 6;
					}
					//将等级写到层中
					$('rank_num').innerText = rank;
				}

				//普通的移动
				else {
					snake_body.unshift(_x + '-' + _y);
					setCellState(snake_body[0]);
					setCellStateBack(snake_body.pop());
				}
			}

			// 判断贪吃蛇头碰到身体的函数
			function eatItself( x,y){
				var nowpos = x + '-' + y;
				for (i = 1 ; i < snake_body.length; i++){
					if (nowpos == snake_body[i])
					return true; 

				}
			}

			// 设置蛇的移动方向以及键盘控制暂停与继续
			function setDirction(){
				  // alert(event.keyCode);
				  if (event.keyCode == 81) window.clearInterval(interval);
				  if (event.keyCode == 82) interval = window.setInterval('snakeMove()',speed);

				switch (event.keyCode){
					case 37:
					if (direction != "right")
					direction = "left";
					break;
					case 38:
					if (direction != "down")
					direction = "up";
					break;
					case 39:
					if (direction != "left")
					direction = "right";
					break;
					case 40:
					if (direction != "up")
					direction = "down";
					break;
				}

			}


			// 初始化食物
			function initFood(){
				var temp = new Array();
				for (i = 0 ; i < max_scope ; i++){
					for (j = 0 ; j < max_scope; j++){
						temp.push(i + '-' + j);
					}
				}

				var addFoodString = temp.join(',')+',';

				for(k = 0 ; k <snake_body.length; k++){
					addFoodString = addFoodString.replace(snake_body[k]+',',"")
				}

				var food_array = addFoodString.split(',');

				food = food_array[parseInt(Math.random()*(food_array.length - 1))]
				setFootState(food);
				// $('display').innerText = addFoodString;

			}

			// function pause(){
			// 	if (event.keyCode == 81) 
			// 		window.clearInterval(interval);
			// }

		</script>
	</head>
	<body onload="initGame()" onkeydown="setDirction()" >
		<div id = "page">
			<div id = "left">
				<table>
					<tbody id = "tbody">
					</tbody>
				</table>
			</div>
			
			<div id = "right">
				<div id = "score">
					<div class = "tag">Score</div>
					<div id = "score_num">0</div>
				</div>
				<div id = "rank">
					<div class = "tag">Rank</div>
					<div id = "rank_num">1</div>
				</div>
				<div id = "notice">NOTICE:按'Q'暂停,'E'继续</div>
			</div>
		</div>
		<!-- <div id = "display"> </div> -->
	</body>
</html>


以下是效果图: ![](http://images2017.cnblogs.com/blog/885599/201708/885599-20170828144621249-460981364.png)
原文地址:https://www.cnblogs.com/neveslalala/p/7442574.html