<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>贪吃蛇小游戏</title>
<style>
body{
margin: 0;
padding: 0;
}
#main{
margin: 100px;
}
.btn{
width: 100px;
height: 40px;
}
.gtitle{
font-size: 25px;
font-weight: bold;
}
#gnum{
color: red;
}
</style>
</head>
<body>
<div id="main">
<h1>贪吃蛇</h1>
<input class="btn" type="button" value="开始游戏" id="begin">
<input class="btn" type="button" value="结束游戏" id="pause">
<span class="gtitle">第<span id="gnum">1</span>关</span>
</div>
<script>
let main = document.getElementById('main');
var showcanvas = false; // 是否开启画布的格子
function Map(atom, xnum, ynum){
this.atom = atom;
this.xnum = xnum;
this.ynum = ynum;
this.canvas = null;
// 创建画布的方法
this.create = function(){
this.canvas = document.createElement('div');
this.canvas.style.cssText = "position: relative; top: 40px; border: 1px solid darkred;background: #FAFAFA";
this.canvas.style.width = this.atom * this.xnum + 'px'; // 画布的宽
this.canvas.style.height = this.atom * this.ynum + 'px';// 画布的高
main.appendChild(this.canvas);
if(showcanvas){
for(var y = 0; y < ynum; y++){
for(var x = 0; x < xnum; x++){
var a = document.createElement('div');
a.style.cssText = "border: 1px solid yellow;";
a.style.width = this.atom + 'px';
a.style.height = this.atom + 'px';
a.style.backgroundColor = "green";
this.canvas.appendChild(a);
a.style.position = 'absolute';
a.style.left = x * this.atom + 'px';
a.style.top = y* this.atom + 'px';
}
}
}
};
};
function Food(map){
this.width = map.atom;
this.height = map.atom;
this.bgcolor = `rgb(${Math.floor(Math.random() * 200)},${Math.floor(Math.random() * 200)},${Math.floor(Math.random() * 200)})`
this.x = Math.floor(Math.random() * map.xnum);
this.y = Math.floor(Math.random() * map.ynum);
this.flag = document.createElement('div');
this.flag.style.width = this.width + 'px';
this.flag.style.height = this.height + 'px';
this.flag.style.borderRadius = '50%';
this.flag.style.position = 'absolute';
this.flag.style.backgroundColor = this.bgcolor;
this.flag.style.left = this.x * this.width + 'px';
this.flag.style.top = this.y * this.height + 'px';
map.canvas.appendChild(this.flag);
}
function Snake(map){
this.width = map.atom;
this.height = map.atom;
this.direction = 'right';
this.body = [
{x: 2, y: 0}, // 蛇头, 第一点
{x: 1, y: 0},
{x: 0, y: 0} // 蛇尾, 第三点
];
// 显示蛇
this.display = function(){
for(let i=0; i<this.body.length; i++){
if(this.body[i].x != null){ // 当吃到食物时,x == null,不能新建, 不然会在0,0处新建一个
var s = document.createElement('div');
// 将节点保存到一个状态变量中,以便以后删除使用
this.body[i].flag = s;
// 设置蛇的样式
s.style.width = this.width + 'px';
s.style.height = this.height + 'px';
s.style.backgroundColor = `rgb(${Math.floor(Math.random() * 200)},${Math.floor(Math.random() * 200)},${Math.floor(Math.random() * 200)})`
s.style.borderRadius = '50%';
// 设置位置
s.style.position = 'absolute';
s.style.left = this.body[i].x * this.width + 'px';
s.style.top = this.body[i].y * this.height + 'px';
map.canvas.appendChild(s);
}
}
};
// 让蛇运动起来
this.run = function(){
for(let i = this.body.length-1; i>0; i--){
this.body[i].x = this.body[i-1].x;
this.body[i].y = this.body[i-1].y;
}
switch (this.direction) {
case "left":
this.body[0].x -= 1;
break;
case "right":
this.body[0].x += 1;
break;
case "up":
this.body[0].y -= 1;
break;
case "down":
this.body[0].y += 1;
break;
default:
break;
}
// 判断蛇头吃到食物,xy和食物的xy重合
if(this.body[0].x == food.x && this.body[0].y == food.y){
// 蛇加一节,根据最后节定
this.body.push({x: null, y: null, flag: null});
// 判断一个设置级别
if(this.body.length > l.slength){
l.set();
}
map.canvas.removeChild(food.flag)
food = new Food(map);
}
// 判断是否出界,蛇头
if(this.body[0].x < 0 || this.body[0].x > map.xnum - 1 || this.body[0].y < 0 || this.body[0].y > map.ynum -1 ){
clearInterval(timer);
alert("游戏结束");
restart(map, this);
return false;
}
// 判断是否和自己重合
for(let i=4; i<this.body.length; i++){
if(this.body[0].x == this.body[i].x && this.body[0].y == this.body[i].y){
clearInterval(timer);
alert("游戏结束");
restart(map, this);
}
}
for(let i=0; i<this.body.length; i++){
if(this.body[i].flag != null){ // 当吃到食物,flag等null,且不能删除
map.canvas.removeChild(this.body[i].flag);
}
}
this.display();
};
}
// 重新开始游戏
function restart(map,snake){
for(let i=0; i < snake.body.length; i++){
map.canvas.removeChild(snake.body[i].flag);
}
snake.body = [
{x:2, y:0},
{x:1, y:0},
{x:0, y:0}
];
snake.direction = "right";
snake.display();
map.canvas.removeChild(food.flag);
food = new Food(map);
}
// 设置级别对象
function Level(){
this.num = 1; // 第几级别
this.speek = 300; // 毫秒, 每开一关, 数量减少20, 速度加快
this.slength = 8; // 每关的长度判断
this.set = function(){
this.num++;
if(this.speek <= 50){
this.speek = 50;
}else{
this.speek -= 50;
}
this.slength += 3;
this.display();
start(); // 重新开始, 速度加快
}
this.display = function(){
document.getElementById('gnum').innerHTML = this.num;
}
}
var l = new Level();
l.display();
// 创建地图对象
var map = new Map(20, 40, 20);
map.create();
// 构造食物对象
var food = new Food(map);
//构造蛇对象
let snake = new Snake(map)
snake.display();
window.onkeydown = function(e){
let event = e || window.event;
switch (event.keyCode) {
case 38:
if(snake.direction != "down"){
snake.direction = "up";
}
break;
case 40:
if(snake.direction != "up"){
snake.direction = "down";
}
break;
case 37:
if(snake.direction != "right"){
snake.direction = "left";
}
break;
case 39:
if(snake.direction != "left"){
snake.direction = "right";
}
break;
default:
break;
}
}
var timer;
function start(){
clearInterval(timer);
timer = setInterval(function(){
snake.run();
},l.speek);
}
document.getElementById('begin').onclick = function(){
start();
}
document.getElementById('pause').onclick = function(){
clearInterval(timer);
}
</script>
</body>
</html>