HTML


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" type="text/css" href="snake.css">
<title>Snake</title>
</head>
<body>
<div class="content">

<div class="btn startBtn"><button></button></div>
<div class="btn pauseBtn"><button></button></div>

<div id="snakeWrap">
</div>

</div>
<script src="snake.js"></script>
</body>
</html>

CSS

.content{
width: 640px;
height: 640px;
margin: 100px auto;
position: relative;
}
.btn{
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
background-color: rgba(0, 0, 0, 0.2);
z-index: 2;
}
.btn button{
background: none;
border: none;
background-size:100% 100%;

cursor: pointer;
outline: none;

position: absolute;
left: 50%;
top: 50%;
}
.startBtn button{
width: 200px;
height: 200px;
background-image: url('./images/player.png');

margin-left: -100px;
margin-top: -100px;
}
.pauseBtn{
display: none;
}
.pauseBtn button{
width: 200px;
height: 200px;
background-image: url('./images/Playerpause.png');

margin-left: -100px;
margin-top: -100px;
}
#snakeWrap{
width: 600px;
height: 600px;
background-color: #225675;
border: 20px solid #7dd9ff;

position: relative;
}
#snakeWrap div{
width: 20px;
height: 20px;
}
.snakeHead{
background-image: url('./images/head.png');
background-size: cover;
background-color: seashell;
}
.snakeBody{
background-color: #000;
border-radius: 50%;
}
.food{
width: 20px;
height: 20px;
background-color: red;
border-radius: 50%;
}

JavaScript

var sw=20,	//一个方块的宽
sh=20, //一个方块的高
tr=30, //行数
td=30; //列数

var snake=null, //蛇的实例
food=null, //食物的实例
game=null; //游戏的实例

function Square(x,y,classname){
//0,0
//20,0 1,0
//40,0 2,0
this.x=x*sw;
this.y=y*sh;
this.class=classname;

this.viewContent=document.createElement('div'); //Dom元素
this.viewContent.className=this.class;
this.parent=document.getElementById('snakeWrap'); //方块的父级

}
Square.prototype.create=function(){
this.viewContent.style.position='absolute';
this.viewContent.style.width=sw+'px';
this.viewContent.style.height=sh+'px';
this.viewContent.style.left=this.x+'px';
this.viewContent.style.top=this.y+'px';

this.parent.appendChild(this.viewContent);
};
Square.prototype.remove=function(){
this.parent.removeChild(this.viewContent);
};

//蛇
function Snake(){
this.head=null; //蛇头
this.tail=null; //蛇尾
this.pos=[]; //存储在蛇身上的每一个方块的位置

this.directionNum={ //蛇走的方向

left:{
x:-1,
y:0,
rotate:180 //蛇头在不同的方向中进行旋转,
},
right:{
x:1,
y:0,
rotate:0
},
up:{
x:0,
y:-1,
rotate:-90
},
down:{
x:0,
y:1,
rotate:90
}
}
}
Snake.prototype.init=function(){
//创建蛇头
var snakeHead=new Square(2,0,'snakeHead');
snakeHead.create();
this.head=snakeHead; //存储蛇头信息
this.pos.push([2,0]); //蛇头位置存储

//创建蛇身体
var snakeBody1=new Square(1,0,'snakeBody');
snakeBody1.create();
this.pos.push([1,0]); //蛇身1的坐标存储

var snakeBody2=new Square(0,0,'snakeBody');
snakeBody2.create();

this.tail=snakeBody2; //把蛇尾存起来
this.pos.push([0,0]); //蛇身2的坐标存储

//形成链表关系
snakeHead.last=null;
snakeHead.next=snakeBody1;

snakeBody1.last=snakeHead;
snakeBody1.next=snakeBody2;

snakeBody2.last=snakeBody1;
snakeBody2.next=null;

//给蛇添加一个属性,用来表示蛇的方向。
this.direction=this.directionNum.right;
};
//这个方法用来获取 蛇头的下一个位置对应的元素,要个根据元素做不同的事情
Snake.prototype.getNextPos=function(){
var nextPos=[ //蛇头要走的下一个点的坐标
this.head.x/sw + this.direction.x,
this.head.y/sh + this.direction.y
]

//游戏结束条件

//撞自己
var selfCollied=false;
this.pos.forEach(function(value){
if(value[0]==nextPos[0] && value[1]==nextPos[1]){
//如果数组中的两个数据都相等,就说明下一个点在蛇身上里面能找到,代表撞到自己。
selfCollied=true;
}
});
if(selfCollied){
console.log('撞到自己');

this.strategies.die.call(this);

return;
}
//撞墙
if(nextPos[0]<0 || nextPos[1]<0 || nextPos[0]>td-1 || nextPos[1]>tr-1){
console.log('撞墙了');

this.strategies.die.call(this);

return;
}
//吃食物
// this.strategies.eat();
if(food && food.pos[0]==nextPos[0] && food.pos[1]==nextPos[1]){
//这个条件成立说明现在蛇头要走的下一个点是食物的位置。
console.log('吃食物')
this.strategies.eat.call(this)
return;
}

//移动
this.strategies.move.call(this);

};

//碰撞处理
Snake.prototype.strategies={

move:function(format){ //决定是否删除蛇尾
//创建新身体(在旧蛇头的位置)
var newBody=new Square(this.head.x/sw,this.head.y/sh,'snakeBody');
//更新链表关系
newBody.next=this.head.next;
newBody.next.last=newBody;
newBody.last=null;

this.head.remove();
newBody.create();

//创建一个新蛇头(蛇头下一个要走的点)
var newHead=new Square(this.head.x/sw + this.direction.x,this.head.y/sh + this.direction.y,'snakeHead')
//更新链表关系
newHead.next=newBody;
newHead.last=null;
newBody.last=newHead;
newHead.viewContent.style.transform='rotate('+this.direction.rotate+'deg)';
newHead.create();

//蛇身上的每一个方块的坐标更新
//this.pos
this.pos.splice(0,0,[this.head.x/sw + this.direction.x,this.head.y/sh + this.direction.y]);
this.head=newHead; //更新头部信息

if(!format){
this.tail.remove();
this.tail=this.tail.last;

this.pos.pop();
}

},
eat:function(){
this.strategies.move.call(this,true);

createFood();
game.score++;
},
die:function(){
console.log('死');
game.over();
}
}
snake=new Snake();
// snake.init();
// snake.getNextPos();

//创建食物
function createFood(){
//食物随机坐标
var x=null;
var y=null;

var include=true; //随机生成的坐标 true在蛇身上!(需要继续循环) false不在蛇身上(不循环)

while(include){
x=Math.round(Math.random()*(td-1));
y=Math.round(Math.random()*(tr-1));

snake.pos.forEach(function(value){
if(x!=value[0] && y!=value[1]){
//随即坐标不在蛇身上
include=false
}
});

}

//生成食物
food=new Square(x,y,'food');
food.pos=[x,y]; //存储以下生成食物的坐标,用于跟蛇头要走的下一个点做对比

var foodDom=document.querySelector('.food');
if(foodDom){
foodDom.style.left=x*sw +'px';
foodDom.style.top=y*sh +'px';
}else{
food.create();
}
}


//创建游戏逻辑
function Game(){
this.timer=null;
this.score=0;
}
Game.prototype.init=function(){
snake.init();
createFood();

document.onkeydown=function(ev){
if(ev.which==37 && snake.direction!=snake.directionNum.right){
snake.direction=snake.directionNum.left;
}else if(ev.which==38 && snake.direction!=snake.directionNum.down){
snake.direction=snake.directionNum.up;
}else if(ev.which==39 && snake.direction!=snake.directionNum.left){
snake.direction=snake.directionNum.right;
}else if(ev.which==40 && snake.direction!=snake.directionNum.up){
snake.direction=snake.directionNum.down;
}
}
this.start();
}
Game.prototype.start=function(){
this.timer=setInterval(function(){
snake.getNextPos();
},200);
}
Game.prototype.pause=function(){
clearInterval(this.timer);
}
Game.prototype.over=function(){
clearInterval(this.timer);
alert('你的得分为:'+ this.score);

//游戏回归初始状态
var snakeWrap=document.getElementById('snakeWrap');
snakeWrap.innerHTML = '';

snake=new Snake();
game=new Game();

var startBtnWrap=document.querySelector('.startBtn');
startBtnWrap.style.display='block';

}

//开始游戏
game=new Game();

var startBtn=document.querySelector('.startBtn button');

startBtn.onclick=function(){
startBtn.parentNode.style.display='none';
game.init();
};

//暂停游戏
var snakeWrap=document.getElementById('snakeWrap');

var pauseBtn=document.querySelector('.pauseBtn button');

snakeWrap.onclick=function(){

game.pause();

pauseBtn.parentNode.style.display='block';
}
pauseBtn.onclick=function(){
game.start();
pauseBtn.parentNode.style.display='none';
}