效果图:
功能:
①自动移动
②可以吃食物以增加蛇身长度
③有边界设置
④有暂停键设置
思路:
①先利用table生成地图,并且添加dataset属性;
②再生成 蛇。蛇是一个数组,初始化的时候渲染到地图上就可。
③生成 食物,并渲染到地图上即可
注意:dataset属性的设置可以为地图添加类似于(x,y)格式的坐标(这篇教程里用的是 x-y 的格式,实际上是 td${x}-${y}
,但设置了用于解析格式的函数)
话不多说,直接上代码,我的思路都在代码里了。
记得先看main函数,然后再慢慢来。
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>指定表格变色</title>
<style>
td {
width: 20px;
height: 20px;
}
.red {
background-color: red;
}
.white {
background-color: #fff;
}
.orange{
background-color: orange;
}
</style>
</head>
<body>
<div align="center">
<table border="1">
<thead>
<th colspan="10">myTable</th>
</thead>
<tbody>
</tbody>
</table>
<input type="text" autofocus>
<button>暂停</button>
</div>
</body>
<script>
let tb = document.querySelector('tbody')
let ipt = document.querySelector('input')
let btn=document.querySelector('button')
let snake = ['1-2', '1-3', '1-4']//蛇的初始化
let current = []//要删除的那个
let mySet = null//日后设置 定时器用
let maxWidth=10//地图大小
let meal=''//食物
function makeTable() { //生成表格
for (let y = 0; y < maxWidth; y++) {
let newTr = document.createElement('tr')
for (let x = 0; x < maxWidth; x++) {
let newTd = document.createElement('td')
newTd.dataset.position = `td${x}-${y}`
newTr.appendChild(newTd)
}
tb.appendChild(newTr)
}
}
ipt.addEventListener('keyup', (e) => { //监听输入的值 并 重置 值
// console.log(e.key)
switch (e.key) {
case 'd': {}
case 'D': {}
case 'ArrowRight': { //→
ipt.value = '→'
break;
}
case 'a': {}
case 'A': {}
case 'ArrowLeft': { //←
ipt.value = '←'
break;
}
case 'W': {}
case 'w': {}
case 'ArrowUp': { //↑
ipt.value = '↑'
break;
}
case 's': {}
case 'S': {}
case 'ArrowDown': { //↓
ipt.value = '↓'
break;
}
}
// console.log(mySet)
//自动移动
if(mySet){
clearInterval(mySet)
}
mySet = setInterval(moveSnake,500)
// console.log(mySet)
//手动移动
// moveSnake()
//自动移动 和 手动移动 取其一就可
})
function makeSnake() { //生成蛇
// console.log(snake)
if (!snake) return;
snake.forEach(ele => {
parseIpt(ele)
})
}
function moveSnake() { //蛇的移动
let target = snake[0] //获取蛇头
// console.log(target)
target = target.split('-')
let targetX = Number(target[0]) //蛇头的 x 坐标
let targetY = Number(target[1]) //蛇头的 y 坐标
switch (ipt.value) {//判断移动方向
case '↑': { //y-=1
targetY -= 1
break;
}
case '↓': { //y+=1
targetY += 1
break;
}
case '←': { //x-=1
targetX -= 1
break;
}
case '→': { //x+=1
targetX += 1
break;
}
}
//移动
let res = `${targetX}-${targetY}`//获取目标值
snake.unshift(res)//向目标值移动
if(res!=meal){//目标值 不等于 食物
current = snake.pop().split('-') //[num,num] //保持蛇身长度不变
}else{//等于食物 则重新生成 且 增加蛇身长度
makeMeal()
}
makeSnake()//对蛇重新渲染
}
function parseIpt(value) { //解析传入的值
let valArr = value.split('-')//'1-2'-->[1,2]
if (valArr.length != 2 || valArr[0] > maxWidth-1 || valArr[1] > maxWidth-1 || valArr[0] < 0 || valArr[1] < 0) {
location.reload()//页面刷新
return alert('输入数据错误。')
}
// console.log('您输入的坐标为:x=' + valArr[0], 'y=' + valArr[1])
setStyle(valArr[0], valArr[1])
}
function setStyle(x, y) { //对指定的值设置样式
if (current.length != 0) {//如果行动,则 去除 以前存在的 那条蛇
let curTarget = document.querySelector(`[data-position=td${current[0]}-${current[1]}]`)
// curTarget.className = ''
curTarget.removeAttribute('class')
// console.log('上一个-->', current, curTarget)
}
let target = document.querySelector(`[data-position=td${x}-${y}]`)
target.className = 'red'
}
function makeMeal(){//生成食物
let mealX
let mealY
do{
mealX=Math.floor(Math.random()*maxWidth)//0-9
mealY=Math.floor(Math.random()*maxWidth)//0-9
meal=`${mealX}-${mealY}`
}while(snake.some(ele => ele==meal))//如果 生成的 (x,y)在蛇的体内 则重新生成
let target=document.querySelector(`[data-position="td${mealX}-${mealY}"]`)//获取食物所在的单元格位置
target.className='orange'//对食物所在的单元格位置进行渲染
}
btn.onclick=function(){//按下了暂停键
clearInterval(mySet)
}
function main() {
makeTable()//初始化地图
makeSnake()//初始化蛇
makeMeal()//生成食物
}
main()
</script>
</html>
已知的bug:在 与身体朝向 相反的 路径上 移动的时候 会出现空白格子。(只是懒得加逻辑了)
本文章禁止转载,转载请联系作者
友好的交流请放在评论区,谢谢。