<!DOCTYPE html>
<html lang="en">
<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>Document</title>
<link rel="stylesheet" href="../css/maze.css">
</head>
<body>
<div class="maze">
<table>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</table>
</div>
<div class="over"></div>
<script src="../JS/maze.js"></script>
</body>
</html>
* {
margin: 0;
padding: 0;
box-sizing: content-box;
}
.maze {
position: relative;
width: 800px;
height: 800px;
border: 5px solid #bfc;
margin: auto;
}
table {
border-collapse: collapse;
}
td {
box-sizing: border-box;
width: 100px;
height: 100px;
border: 1px solid black;
}
.start {
position: absolute;
width: 100px;
height: 100px;
background-color: brown;
}
.obstacle {
position: absolute;
width: 100px;
height: 100px;
background-color: blue;
}
.over {
display: none;
position: absolute;
top: 230px;
left: 300px;
width: 800px;
height: 200px;
border: 10px solid green;
color: red;
font-size: 20px;
background: rgba(0, 0, 0, .7);
}
//小方块的长宽
const sh = 100
const sw = 100
//坐标节点
class PsNode {
constructor(pos) {
this.pos = pos //坐标数组
this.next = null //指针域
}
}
//位置栈
class PosStack {
constructor() {
this.top = null //头指针
this.base = null //栈底指针
this.length = 0 //栈长度
}
//入栈方法
pushStack(pos) {
const newNode = new PsNode(pos)
if (this.isEmpty()) {
this.top = newNode
this.base = newNode
} else {
newNode.next = this.top
this.top = newNode
}
this.length++
}
// 返回栈顶指针,即当前位置
getTop() {
return this.top.pos
}
//判断栈是否为空
isEmpty() {
if (this.length === 0) { //为空置空指针
this.top = null
this.base = null
return true
} else {
return false
}
}
//转换字符串
elementToString() {
if (this.isEmpty()) {
return '空栈';
} else {
let node = this.top;
let str = '栈顶 ';
while (node.next) {
str += node.pos + '->';
node = node.next;
}
str += node.pos + ' 栈底';
return str;
}
}
}
const obstacleStack = new PosStack() //保存障碍物坐标的栈
const pathStack = new PosStack() //走过路径坐标的栈
pathStack.pushStack([0, 0]) //初始状态
//迷宫中的小方块类
class Square {
//接收类名,定位left,top值(坐标数组的数据)
constructor(classname, left, top) {
this.view = document.createElement('div')
this.view.className = classname
this.view.style.left = left * sw + 'px'
this.view.style.top = top * sh + 'px'
this.parent = document.querySelector('.maze')
}
//将小方块添加到迷宫中
appendSquare() {
this.parent.append(this.view)
}
}
//控制游戏类
let div //开始方块
class Game {
constructor() {
//方块移动的方向
this.direction = {
up: {
top: -1,
left: 0
},
down: {
top: 1,
left: 0
},
left: {
top: 0,
left: -1
},
right: {
top: 0,
left: 1
},
}
this.init()
}
//初始化
init() {
this.initStartSqu() //初始化开始方块
this.initObSqu() //初始化障碍物
this.moveSqu() //初始化绑定移动事件
}
//初始化开始小方块
initStartSqu() {
div = new Square('start', 0, 0) //赋值给全局的变量div
div.appendSquare() //加入迷宫
}
//初始化障碍方块
initObSqu() {
//循环指针
let current = obstacleStack.top
// 循环生成障碍物
while (current.next) {
const posArr = current.pos //保存障碍物坐标
const obs = new Square('obstacle', posArr[1], posArr[0]) //坐标传入
obs.appendSquare() //添加障碍物
current = current.next //修改循环变量
}
//最后一个障碍物
const posArr = current.pos
const obs = new Square('obstacle', posArr[1], posArr[0])
obs.appendSquare()
}
//获取下一个向右的位置
getNextRightPos() {
const nowPos = pathStack.getTop()
const nextPos = [nowPos[0], nowPos[1] + 1]
return nextPos
}
//获取下一个向上的位置
getNextUptPos() {
const nowPos = pathStack.getTop()
const nextPos = [nowPos[0] - 1, nowPos[1]]
return nextPos
}
//获取下一个向下的位置
getNextDownPos() {
const nowPos = pathStack.getTop()
const nextPos = [nowPos[0] + 1, nowPos[1]]
return nextPos
}
//获取下一个向左的位置
getNextLefttPos() {
const nowPos = pathStack.getTop()
const nextPos = [nowPos[0], nowPos[1] - 1]
return nextPos
}
//是否撞到障碍物,which代表下一个位置的方向
isWall(which) {
let nextPos; //保存下一个坐标
if (which === 'up') {
nextPos = this.getNextUptPos() //下一个位置为向上方向
} else if (which === 'down') {
nextPos = this.getNextDownPos() //下一个位置为向下方向
} else if (which === 'left') {
nextPos = this.getNextLefttPos() //下一个位置为向左方向
} else {
nextPos = this.getNextRightPos() //下一个位置为向右方向
}
let current = obstacleStack.top //用于循环的指针
while (current.next) {
//下一个坐标是否存在于障碍物栈中(即撞墙)
if (nextPos[0] === current.pos[0] && nextPos[1] === current.pos[1]) {
return true
}
current = current.next
}
//没设置头节点,加一次查找
if (nextPos[0] === current.pos[0] && nextPos[1] === current.pos[1]) {
return true
}
return false
}
// 判定游戏是否结束
isGameOver() {
let div = document.querySelector('.over')
const topArr = pathStack.getTop()
if (topArr[0] === 7 && topArr[1] === 7) {
div.style.display = 'block'
div.innerHTML = pathStack.elementToString()
}
console.log(div);
}
//绑定事件,控制方块移动
moveSqu() {
document.addEventListener('keyup', (ev) => {
let left = parseInt(div.view.style.left)
let top = parseInt(div.view.style.top)
if (ev.code === 'ArrowUp') { //向上移动
if (!this.isWall('up') && this.getNextUptPos()[0] >= 0) {
pathStack.pushStack(this.getNextUptPos()) // 将走的这一步压入路径栈
console.log(pathStack.elementToString());
div.view.style.top = top + this.direction.up.top * sh + 'px'
this.isGameOver()
}
} else if (ev.code === 'ArrowDown') { //向下移动
if (!this.isWall('down') && this.getNextDownPos()[0] < 8) {
pathStack.pushStack(this.getNextDownPos()) // 将走的这一步压入路径栈
div.view.style.top = top + this.direction.down.top * sh + 'px'
this.isGameOver()
}
} else if (ev.code === 'ArrowLeft') { //向左移动
if (!this.isWall('left') && this.getNextLefttPos()[1] >= 0) {
pathStack.pushStack(this.getNextLefttPos()) // 将走的这一步压入路径栈
div.view.style.left = left + this.direction.left.left * sw + 'px'
this.isGameOver()
}
} else if (ev.code === 'ArrowRight') { //向右边移动
if (!this.isWall('right') && this.getNextRightPos()[1] < 8) {
pathStack.pushStack(this.getNextRightPos()) // 将走的这一步压入路径栈
div.view.style.left = left + this.direction.right.left * sw + 'px'
this.isGameOver()
}
}
})
}
}
obstacleStack.pushStack([0, 2])
obstacleStack.pushStack([0, 6])
obstacleStack.pushStack([1, 2])
obstacleStack.pushStack([1, 6])
obstacleStack.pushStack([2, 4])
obstacleStack.pushStack([2, 5])
obstacleStack.pushStack([3, 1])
obstacleStack.pushStack([3, 2])
obstacleStack.pushStack([3, 3])
obstacleStack.pushStack([4, 3])
obstacleStack.pushStack([5, 1])
obstacleStack.pushStack([5, 5])
obstacleStack.pushStack([6, 1])
obstacleStack.pushStack([6, 2])
obstacleStack.pushStack([6, 3])
obstacleStack.pushStack([6, 5])
obstacleStack.pushStack([6, 6])
obstacleStack.pushStack([7, 0])
const game = new Game()
?
|