一、简单介绍

1.1 效果展示

1.2 实现思路

  • 地图:创建一个 800px * 400px 的 div 元素来充当地图;地图可以看作由 40 x 20 个小 div(宽高都为20px) 元素组成。
  • 食物:创建一个 宽高都为 20px 的 div 充当食物;食物通过 Math.random 分配随机位置。
  • 蛇:创建一个二维数组充当蛇;二维数组存放蛇节(3个蛇身和1个蛇头),一维数组存放蛇节的位置、颜色和下一个蛇节对象。
  • 蛇移动:先移动蛇尾,再移动蛇头。当前移动的蛇节位置为下一个蛇节未移动时的位置。

1.3 涉及技术

DOM操作、面向对象、事件操作和间隔函数setInterval

1.4 项目结构

二、实现步骤

2.1 绘制地图

2.1.1 style.css 文件

1
2
3
4
5
6
7
8
9
10
11
html,body {
margin:0;
padding: 0;
}

.map {
margin: 100px auto;
text-align: center;
background-color: pink;
position: relative;
}

2.1.2 map.js 文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var Map = function(width,height) {
this.width = width;
this.height = height;
this.id = "map";
}

Map.prototype.showMap = function(containerId) {
// 创建地图并设置样式
var mapDiv = document.createElement("div");
mapDiv.style.width = this.width +"px";
mapDiv.style.height = this.height + "px";
mapDiv.className = this.id;
mapDiv.id = this.id;
// 将创建的地图添加到页面中
document.getElementById(containerId).appendChild(mapDiv);
}

2.1.3 game.js 文件创建地图

1
2
3
4
5
6
7
8
var Game = function() {

}

Game.prototype.start = function() {
var map = new Map(800, 400); // 长宽数值必须是2的整数倍
map.showMap("container");
}

2.1.4 index.html 文件开始游戏

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<!DOCTYPE html>
<html lang="zh">

<head>
<meta charset="UTF-8">
<title>贪吃蛇</title>
<link rel="stylesheet" type="text/css" href="css/style.css">
</head>

<body>
<div id="container"></div>
<script type="text/javascript" src="js/map.js"></script>
<script type="text/javascript" src="js/food.js"></script>
<script type="text/javascript" src="js/snake.js"></script>
<script type="text/javascript" src="js/game.js"></script>
<script type="text/javascript">
window.onload = function() {
var game = new Game();
game.start();
}
</script>
</body>

</html>

2.1.5 效果

2.2 绘制食物

2.2.1 food.js 文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
var Food = function(map) {
this.size = 20; // 食物大小
this.xFood = 0; // 食物x坐标
this.yFood = 0; // 食物y坐标
this.map = map; // 坐在地图
this.foodDiv = null; // 地图中的食物
}

Food.prototype.showFood = function() {
// 此处判断确保地图中只有一个食物
if (this.foodDiv === null) {
// 创建食物并设置样式
this.foodDiv = document.createElement("div");
this.foodDiv.style.width = this.foodDiv.style.height = this.size + "px";
this.foodDiv.style.backgroundColor = "red";
this.foodDiv.style.position = "absolute";
// 将食物添加到地图上
document.getElementById(this.map.id).appendChild(this.foodDiv);
}

// 食物步进值:20px
// 食物权值坐标:X轴(0 - map.width/this.size)Y轴(0 - map.height/this.size)
this.xFood = Math.floor(Math.random() * (this.map.width / this.size));
this.yFood = Math.floor(Math.random() * (this.map.height / this.size));
// 设置食物在地图的位置
this.foodDiv.style.left = this.xFood * this.size + "px";
this.foodDiv.style.top = this.yFood * this.size + "px";
}

2.2.2 game.js 文件创建地图和食物对象

1
2
3
4
5
6
7
8
9
10
11
var Game = function() {

}

Game.prototype.start = function() {
var map = new Map(800, 400); // 长宽数值必须是2的整数倍
map.showMap("container");

var food = new Food(map);
food.showFood();
}

2.2.3 效果

2.3 绘制小蛇

2.3.1 snake.js 文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
var Snake = function(food) {
this.size = 20;
// 初始化蛇{x坐标,y坐标,颜色,蛇节对象}
this.snakeBody = [
{x:0,y:1,color:"black",obj:null},// 蛇身
{x:1,y:1,color:"black",obj:null},// 蛇身
{x:2,y:1,color:"black",obj:null},// 蛇身
{x:3,y:1,color:"white",obj:null}// 蛇头
];
this.direction = "right"; // 蛇移动方向
this.food = food; //食物
}

// 显示蛇
Snake.prototype.showSnake = function() {
//遍历蛇节,依次创建
for (var i = 0; i < this.snakeBody.length; i++){
//此处判断为了避免重复创建蛇节
if (this.snakeBody[i].obj == null) {
// 创建蛇节div,设置样式
this.snakeBody[i].obj = document.createElement("div");
this.snakeBody[i].obj.style.width = this.snakeBody[i].obj.style.height = this.size + "px";
this.snakeBody[i].obj.style.backgroundColor = this.snakeBody[i].color;
this.snakeBody[i].obj.style.position = "absolute";
// 追加蛇节
document.getElementById(this.food.map.id).appendChild(this.snakeBody[i].obj);
}
// 设置蛇在地图中的位置
this.snakeBody[i].obj.style.left = this.snakeBody[i].x * this.size + "px";
this.snakeBody[i].obj.style.top = this.snakeBody[i].y * this.size + "px";

}
}

2.3.2 game.js 文件创建地图、食物和蛇对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var Game = function() {

}

Game.prototype.start = function() {
var map = new Map(800, 400); // 长宽数值必须是2的整数倍
map.showMap("container");

var food = new Food(map);
food.showFood();

var snake = new Snake(food);
snake.showSnake();

}

2.3.3 效果

2.4 小蛇移动

2.4.1 snake.js 文件,添加move方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// 移动蛇
Snake.prototype.move = function() {
// 非蛇头蛇节(当前蛇节的新坐标 为 下个蛇节的旧坐标)
for (var i=0; i<this.snakeBody.length -1; i++) {
this.snakeBody[i].x = this.snakeBody[i+1].x;
this.snakeBody[i].y = this.snakeBody[i+1].y;
}

// 设置蛇头位置
if (this.direction == "right") {
// 蛇头x坐标累加
this.snakeBody[this.snakeBody.length - 1].x += 1;
}
if (this.direction == "left") {
// 蛇头x坐标累加
this.snakeBody[this.snakeBody.length - 1].x -= 1;
}
if (this.direction == "up") {
// 蛇头x坐标累加
this.snakeBody[this.snakeBody.length - 1].y -= 1
}
if (this.direction == "down") {
// 蛇头x坐标累加
this.snakeBody[this.snakeBody.length - 1].y += 1;
}

this.showSnake();
}

2.4.2 game.js 文件使用 interval 函数调用蛇对象的move方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var Game = function() {

}

Game.prototype.start = function() {
var map = new Map(800, 400); // 长宽数值必须是2的整数倍
map.showMap("container");

var food = new Food(map);
food.showFood();

var snake = new Snake(food);
snake.showSnake();

setInterval(function() {
snake.move();
}, 100);

}

2.5 控制小蛇移动方向

game.js 添加键盘按下事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
var Game = function() {

}

Game.prototype.start = function() {
var map = new Map(800, 400); // 长宽数值必须是2的整数倍
map.showMap("container");

var food = new Food(map);
food.showFood();

var snake = new Snake(food);
snake.showSnake();

setInterval(function() {
snake.move();
}, 100);

// 键盘控制
document.onkeydown = function(e) {
switch (e.keyCode) {
case 37:
snake.direction = "left";
break;
case 38:
snake.direction = "up";
break;
case 39:
snake.direction = "right";
break;
case 40:
snake.direction = "down";
break;
}
snake.showSnake();
}
}

2.6 小蛇吃食物

snake.js 文件在 move 方法 this.showSnake() 之前添加逻辑判断

1
2
3
4
5
6
7
8
9
10
11
12
// 蛇头坐标
var xSnakeHead = this.snakeBody[this.snakeBody.length -1].x;
var ySnakeHead = this.snakeBody[this.snakeBody.length -1].y;

//判断蛇吃否吃到食物
if (xSnakeHead == this.food.xFood && ySnakeHead == this.food.yFood) {
// 增加蛇长
var newBody = {x:this.snakeBody[0].x,y:this.snakeBody[0].y,color:"black",obj:null};
this.snakeBody.unshift(newBody);
// 食物消失,再随机生成
this.food.showFood();
}

2.7 小蛇移动范围

snake.js 文件在 move 方法 this.showSnake() 之前添加逻辑判断

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 控制小蛇移动范围
if (xSnakeHead < 0 || xSnakeHead >= this.food.map.width/this.size
|| ySnakeHead <0 || ySnakeHead >= this.food.map.height/this.size) {
alert("游戏结束!");
window.location.reload();
}

// 不能吃自己
for (var j=0; j<this.snakeBody.length -1; j++) {
// 蛇头坐标 = 蛇身坐标,游戏结束
if (this.snakeBody[j].x == xSnakeHead && this.snakeBody[j].y == ySnakeHead) {
alert("游戏结束!");
window.location.reload();
}
}

三、源码下载

贪吃蛇下载