趁着闲下来 做个小游戏玩玩
先看看效果
绘制网格
trunk:蛇身体 food:食物 isHead:蛇头
<template>
<div class="snake">
<div class="grid-container">
<div class="grid-row" v-for="(row,index) in gridList" :key="index">
<div class="grid-item" v-for="(item,index2) in row" :key="index2"
:class="{ 'trunk': item===1, 'food': item===2,'isHead': index==bodyList[0].x&&bodyList[0].y===index2}">
</div>
</div>
</div>
<p v-if="state===2" @click="init">你输了 点击重来</p>
</div>
</template>
data() {
return {
n: 16, //行列数
gridList: [],//宫格
bodyList: [],//蛇身位置存储
direction: 39,//方向
timer: "",//定时器
loading: false,
state: 1,//游戏状态
};
},
.snake {
padding: 20px;
.grid-container {
background-color: #2196f3;
padding: 10px;
box-sizing: content-box;
}
.grid-row {
display: flex;
}
.grid-item {
background-color: rgba(255, 255, 255, 0.8);
border: 1px solid rgba(0, 0, 0, 0.8);
font-size: 30px;
text-align: center;
width: 40px;
height: 40px;
display: inline-block;
}
.trunk {
background-color: black;
}
.food {
background-color: yellow;
}
.isHead {
background-color: red;
}
}
methods: {
init() {
let arr = Array.from(Array(this.n), () => Array(this.n).fill(0));
//生成蛇的初始位置
let x = Math.round(this.n / 2);
let y = Math.round(this.n / 2);
arr[x][y] = 1;
arr[x][y - 1] = 1;
this.bodyList = [
{ x, y },
{ x: x, y: y - 1 },
];
this.gridList = arr;
},
}
效果如图
生成食物
randomFood() {
let x = Math.round(Math.random() * this.n);
let y = Math.round(Math.random() * this.n);
let arr = [...this.gridList];
if (arr[x][y] !== 0) {
// 如果出生点位在不是空白位 则重新调用
this.randomFood();
return;
} else {
arr[x][y] = 2;
this.gridList = arr;
}
},
键盘监听
monitorKeydown() {
let _this = this;
//监听键盘事件
document.onkeydown = function (e) {
let key = window.event.keyCode;
if (key === 32) {
//空格暂停
_this.endGame();
return false;
}
// 防止连点
if (_this.loading) {
return false;
}
// 37左 38上 39右 40下
// 转向方向如跟当前方向对立 则不进行转向
if (key === 37 || key === 38 || key === 39 || key === 40) {
if (key === 37 && _this.direction === 39) {
return false;
} else if (key === 39 && _this.direction === 37) {
return false;
} else if (key === 38 && _this.direction === 40) {
return false;
} else if (key === 40 && _this.direction === 38) {
return false;
}
_this.direction = key;
_this.loading = true;
_this.action();
}
};
},
//结束游戏
endGame() {
clearInterval(this.timer);
this.state = 2;
},
方向移动
采用定时器 触发移动事件
这里采用一个技巧 由于蛇移动是连着身子的 所以 蛇身移动后位置[i] = 蛇身移动移动前位置[i+1] 然后处理蛇头和蛇尾就可以
action() {
if (this.timer) {
clearInterval(this.timer);
}
this.timer = setInterval(this.crawl, 500);
},
crawl() {
const { direction, n } = this;
let gridList = [...this.gridList];
let bodyList = [...this.bodyList];
let movex = 0,
movey = 0;
//边界处理
if (direction === 39) {
if (bodyList[0].y >= n - 1) {
this.endGame();
return false;
}
movey = 1;
} else if (direction === 40) {
if (bodyList[0].x >= n - 1) {
this.endGame();
return false;
}
movex = 1;
} else if (direction === 37) {
if (bodyList[0].y <= 0) {
this.endGame();
return false;
}
movey = -1;
} else {
if (bodyList[0].x <= 0) {
this.endGame();
return false;
}
movex = -1;
}
let start = bodyList[0],
end = bodyList[bodyList.length - 1];
// 蛇头前进
gridList[start.x + movex][start.y + movey] = 1;
// 蛇身依次前进
bodyList.forEach((item, index) => {
if (index < bodyList.length - 1) {
let next = bodyList[index + 1];
gridList[item.x][item.y] = gridList[next.x][next.y];
}
});
//更新蛇的记录位置
bodyList = bodyList.map((item, index) => {
if (index === 0) {
return {
x: start.x + movex,
y: start.y + movey,
};
} else {
let next = bodyList[index - 1];
return next;
}
});
//蛇尾处理
gridList[end.x][end.y] = 0;
this.gridList = gridList;
this.bodyList = bodyList;
this.loading = false;
},
剩下就是碰到食物 或者蛇头碰到自己时的处理
if (gridList[start.x + movex][start.y + movey] === 1) { //碰到自身游戏结束
this.endGame();
return false;
} else if (gridList[start.x + movex][start.y + movey] === 2) { //碰到食物 加进蛇身数组
gridList[start.x + movex][start.y + movey] = 1;
bodyList.unshift({
x: start.x + movex,
y: start.y + movey,
});
this.$nextTick(() => {
this.randomFood();
});
}
大功告成 又是摸鱼的一天