在线预览
HTML代码
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>贪吃蛇</title>
<style>
* {
margin: 0;
padding: 0;
}
.container {
margin: auto;
position: relative;
}
table {
border-collapse: collapse;
border: 1px solid #e6e6e6;
margin: auto;
}
td {
height: 20px;
width: 20px;
border: 1px solid #e6e6e6;
}
td div {
width: 100%;
height: 100%;
}
button {
border: 1px solid #e6e6e6;
margin-bottom: 20px;
width: 100px;
height: 30px;
border-radius: 5px;
}
.mask {
position: absolute;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background-color: rgba(0, 0, 0, 0.5);
}
.mask1 {
display: block;
}
.mask2 {
display: none;
}
.menu,
.warn {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.prompt {
position: absolute;
left: 0;
top: 0;
}
.food {
border-radius: 50%;
}
.warn {
width: 400px;
height: 220px;
background-color: #000;
border-radius: 10px;
text-align: center;
color: #fff;
font-size: 16px;
}
.warn p {
margin: 40px 0;
font-size: 30px;
}
.warn button {
width: 100px;
height: 40px;
}
.over {
display: none;
}
.over div {
color: #fff;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
</style>
</head>
<body>
<div class="container">
<table>
</table>
<div class="prompt">
<div class="score">
得分:<span>0</span>
</div>
<div class="level">
关卡:<span>1</span>
</div>
<div class="speed">
速度:<span>150</span>
</div>
</div>
<div class="mask mask1">
<div class="menu">
<button class="normal">普通模式</button><br>
<button class="pass">过关模式</button><br>
<button class="avoid">躲避模式</button><br>
</div>
</div>
<div class="mask mask2">
<div class="warn">
</div>
</div>
<div class="mask over">
<div>
<p>恭喜你通关了!</p><br>
<button>下一关</button>
</div>
</div>
<div class="parameter">
</div>
</div>
<script src="index.js"></script>
</body>
</html>
JS代码
function $(id) {
return document.getElementById(id);
}
function $$(selector) {
return document.querySelector(selector);
}
function Snake(ele) {
this.speed = 150;
this.snakeBody = [];
this.pause = false;
this.score = 0;
this.level = 1;
this.mode = null;
this.rows = 30;
this.cols = 30;
this.ele = ele;
this.len = 3;
this.foodNum = 5;
this.obstacleNum = 10;
this.keyCode = null;
this.movetimerId = null;
this.timeTimerId = null;
this.increaseTime = 30000;
this.endScore = 2000;
}
Snake.prototype = {
init: function() {
var html = '';
for (var i = 0; i < this.rows; i++) {
html += '<tr>';
for (var j = 0; j < this.cols; j++) {
html += '<td id="' + i + '_' + j + '">' + '<div id="' + i + '_' + j + '_div' + '"></div>' + '</td>';
}
html += '</tr>';
}
this.ele.children[0].innerHTML = html;
this.createSnake();
this.createFood(this.foodNum);
this.keyEvent();
},
createSnake: function() {
for (var i = this.len - 1; i >= 0; i--) {
this.snakeBody.push(0 + '_' + i);
$(0 + '_' + i).style.backgroundColor = this.randomColor();
}
},
createFood: function(num) {
while (num) {
var coordinate = this.randomCoordinate();
if ($(coordinate[0]).style.backgroundColor === '' && $(coordinate[1]).style.backgroundColor === '') {
$(coordinate[1]).style.backgroundColor = this.randomColor();
$(coordinate[1]).className = 'food';
num--;
}
}
},
createObstacle: function(num) {
while (num) {
var coordinate = this.randomCoordinate();
if ($(coordinate[0]).style.backgroundColor === '' && $(coordinate[1]).style.backgroundColor === '') {
$(coordinate[0]).style.backgroundColor = '#000';
num--;
}
}
},
keyEvent: function() {
document.onkeydown = function(event) {
switch(event.keyCode) {
case 37:
case 38:
case 39:
case 40:
this.keyCode = event.keyCode;
this.createTimer();
break;
case 32:
if (!this.pause) {
this.clearTimer();
this.pause = true;
} else {
this.createTimer();
this.pause = false;
}
break;
}
}.bind(this);
},
randomColor: function() {
var color = (parseInt(Math.random() * 0xffffff)).toString(16);
return color.length === 6? '#' + color : '#' + color + '0';
},
randomCoordinate: function() {
var x = parseInt(Math.random() * 30);
var y = parseInt(Math.random() * 30);
return [x + '_' + y, x + '_' + y + '_div'];
},
snakeMove: function(keyCode) {
var coordinate = this.snakeBody[0].split('_');
var x = coordinate[0];
var y = coordinate[1];
switch(this.keyCode) {
case 37:
y--;
if (y == this.snakeBody[1].split('_')[1]) {
y += 2;
}
break;
case 38:
x--;
if (x == this.snakeBody[1].split('_')[0]) {
x += 2;
}
break;
case 39:
y++;
if (y == this.snakeBody[1].split('_')[1]) {
y -= 2;
}
break;
case 40:
x++;
if (x == this.snakeBody[1].split('_')[0]) {
x -= 2;
}
break;
}
if (this.statusCheck(x, y)) {
this.snakeBody.unshift(x + '_' + y);
var arry = this.snakeBody;
for (var i = 0, len = arry.length - 1; i < len; i++) {
$(arry[i]).style.backgroundColor = $(arry[i + 1]).style.backgroundColor;
}
$(arry.pop()).style.backgroundColor = '';
}
},
statusCheck: function(x, y) {
if (x < 0 || y < 0 || x >= this.rows || y >= this.cols) {
this.popupPrompt('撞墙了!');
} else if ($(x + '_' + y).style.backgroundColor == 'rgb(0, 0, 0)') {
this.popupPrompt('撞到障碍物了!');
} else if ($(x + '_' + y + '_div').style.backgroundColor != '') {
this.eatFood(x, y);
this.isOver();
return false;
} else {
var tempXY = x + '_' + y;
var arry = this.snakeBody;
for (var i = 3, len = arry.length; i < len; i++) {
if (tempXY == arry[i]) {
this.popupPrompt('咬到自己了!');
}
}
}
return true;
},
popupPrompt: function(str) {
this.level = 1;
this.speed = 150;
this.resetPrompt();
document.onkeydown = '';
clearInterval(this.timeTimerId);
this.timeTimerId = null;
this.clearTimer();
var mask2 = $$('.mask2');
var str = '<p>' + str + '</p>';
str += '<button>重新开始游戏</button>';
$$('.warn').innerHTML = str;
mask2.style.display = 'block';
$$('.warn button').onclick = function() {
mask2.style.display = 'none';
this.snakeBody = [];
this.init();
switch(this.mode) {
case 1:
this.firstMode();
break;
case 3:
this.thirdMode();
break;
}
}.bind(this);
},
checkMode: function() {
$$('.menu').onclick = function(event) {
var mask1 = $$('.mask1');
var target = event.target;
switch(target.className) {
case 'normal':
this.init();
this.firstMode();
this.mode = 1;
mask1.style.display = 'none';
break;
case 'pass':
this.init();
this.mode = 2;
mask1.style.display = 'none';
break;
case 'avoid':
this.init();
this.thirdMode();
this.mode = 3;
mask1.style.display = 'none';
break;
}
}.bind(this);
},
eatFood: function(x, y) {
this.snakeBody.unshift(x + '_' + y);
$(x + '_' + y).style.backgroundColor = $(x + '_' + y + '_div').style.backgroundColor;
$(x + '_' + y + '_div').style.display = 'none';
this.score += 100;
$$('.score span').innerHTML = this.score;
this.createFood(1);
this.isOver();
},
createTimer: function() {
var self = this;
if (!this.movetimerId) {
this.movetimerId = setInterval(function() {
self.snakeMove(self.keyCode);
}, self.speed);
}
},
clearTimer: function() {
clearInterval(this.movetimerId);
this.movetimerId = null;
},
firstMode: function() {
var self = this;
if (!this.timeTimerId) {
this.timeTimerId = setInterval(function() {
self.speed -= 10;
$$('.speed span').innerHTML = self.speed;
self.clearTimer();
self.createTimer();
}, this.increaseTime);
}
},
secondMode: function() {
this.speed -= 10;
$$('.speed span').innerHTML = this.speed;
},
thirdMode: function() {
this.createObstacle(this.obstacleNum);
var self = this;
if (!this.timeTimerId) {
this.timeTimerId = setInterval(function() {
self.speed -= 10;
$$('.speed span').innerHTML = self.speed;
self.clearTimer();
self.createTimer();
}, this.increaseTime);
}
},
isOver: function() {
var flag = false;
switch(this.mode) {
case 1:
if (this.snakeBody.length == this.cols * this.rows - 10) {
this.score = 0;
flag = true;
}
break;
case 2:
case 3:
if (this.score == this.endScore) {
this.score = 0;
flag = true;
}
break;
}
if (flag) {
document.onkeydown = '';
clearInterval(this.timeTimerId);
this.timeTimerId = null;
this.clearTimer();
$$('.over').style.display = 'block';
$$('.over button').onclick = function() {
$$('.over').style.display = 'none';
switch(this.mode) {
case 1:
this.popupPrompt('游戏结束,恭喜你已经达到了人生的巅峰!');
case 2:
if (this.level == 10) {
this.popupPrompt('游戏结束,恭喜你已经达到了人生的巅峰!');
} else {
this.level++;
this.snakeBody = [];
this.secondMode();
this.resetPrompt();
this.init();
break;
}
case 3:
if (this.level == 10) {
this.popupPrompt('游戏结束,恭喜你已经达到了人生的巅峰!');
} else {
this.level++;
this.obstacleNum += 5;
this.snakeBody = [];
this.thirdMode();
this.resetPrompt();
this.init();
break;
}
}
}.bind(this);
}
},
resetPrompt: function() {
this.score = 0;
$$('.score span').innerHTML = this.score;
$$('.speed span').innerHTML = this.speed;
$$('.level span').innerHTML = this.level;
}
}
new Snake($$('.container')).checkMode();