(八)项目三日志 二
物联网工程 - 李涵 - 182210713119
Github:https://github.com/kevin-lh/SoftwarePractice/tree/main/Map
前言
实现了迷宫生成
一、系统框架
系统框架如上图所示,实现了需求分析中的要求,并增加了附加功能,可实时显示步数,撞墙死路会有提示
二、 文件结构
项目结构如上图所示,仍应用electron框架搭建gui,开发语言使用HTML+css+JavaScript
二、详细设计
2.1 UI设计
由于某些原因,来不及对界面进行美化,有些丑陋,但实现了基本功能。
2.2 功能设计
2.2.1 地图生成函数
采用prim算法给每个节点赋值,0为通路,1为墙
//绘制初始格子
Maze.prototype.generate = function () {
// 生成 2R+1 行 2R+1 列数组
this.mazeDataArray = [];
for (let i = 0; i < 2 * this.col + 1; i++) {
let arr = [];
for (let j = 0; j < 2 * this.row + 1; j++) {
// 设置墙和初始格子
if (i % 2 == 0 || j % 2 == 0) {
arr.push({ //设置初始格子
value: 0,
i: i,
j: j
});
} else {
arr.push({ //设置墙
value: 1,
isVisited: false,
i: i,
j: j
});
}
}
this.mazeDataArray[i] = arr;
}
// 随机选择一点作为 currentNode
let currentNode = this.mazeDataArray[2 * this.random(this.row) + 1][2 * this.random(this.col) + 1];
currentNode.isVisited = true;
// 访问过的节点列表
let visitedList = [];
visitedList.push(currentNode);
// 循环以下操作,直到所有的格子都被访问到。
while (currentNode.isVisited) {
// 得到当前访问格子的四周(上下左右)的格子
let upNode = this.mazeDataArray[currentNode.i - 2] ? this.mazeDataArray[currentNode.i - 2][currentNode.j] : {isVisited: true};
let rightNode = this.mazeDataArray[currentNode.j + 2] ? this.mazeDataArray[currentNode.i][currentNode.j + 2] : {isVisited: true};
let downNode = this.mazeDataArray[currentNode.i + 2] ? this.mazeDataArray[currentNode.i + 2][currentNode.j] : {isVisited: true};
let leftNode = this.mazeDataArray[currentNode.j - 2] ? this.mazeDataArray[currentNode.i][currentNode.j - 2] : {isVisited: true};
let neighborArray = [];
if (!upNode.isVisited) {
neighborArray.push(upNode);
}
if (!rightNode.isVisited) {
neighborArray.push(rightNode);
}
if (!downNode.isVisited) {
neighborArray.push(downNode);
}
if (!leftNode.isVisited) {
neighborArray.push(leftNode);
}
// 在这些格子中随机选择一个没有在访问列表中的格子,
// 如果找到,则把该格子和当前访问的格子中间的墙打通(置为0),
if (neighborArray.length !== 0) { // 如果找到
let neighborNode = neighborArray[this.random(neighborArray.length)];
this.mazeDataArray[(neighborNode.j + currentNode.j) / 2][(neighborNode.i + currentNode.i) / 2].value = 1;
neighborNode.isVisited = true;
visitedList.push(neighborNode);
currentNode = neighborNode;
} else {
// 把该格子作为当前访问的格子,并放入访问列表。
// 如果周围所有的格子都已经访问过,则从已访问的列表中,随机选取一个作为当前访问的格子。
currentNode = visitedList[this.random(visitedList.length)];
if (!currentNode) {
// visitedList为空时 跳出循环
break;
}
currentNode.isVisited = true;
// 从 visitedList 中删除随机出来的当前节点
let tempArr = [];
visitedList.forEach(item => {
if (item !== currentNode) {
tempArr.push(item);
}
});
visitedList = tempArr;
}
}
//start 0,0
// 1,0 => 0
this.mazeDataArray[this.start[0]][this.start[1]] = {
i: this.start[0],
j: this.start[1],
value: 1
};
// this.mazeDataArray[this.start[0]+1][this.start[0]+1]={value:1};
// end 9,9
// 20,21 =>1
this.mazeDataArray[this.end[0]][this.end[1]] = {
i: this.end[0],
j: this.end[1],
value: 1
};
// this.mazeDataArray[this.end[0]][this.end[1]-1]={value:1};
};
三、功能演示
请见下文!!!