1.审题:最短路径&&二维矩阵
则正常而言,a*算法得出的结果不一定最短
但如果F=G+H中,H恒为0的情况,则可以视作Dijkstra的一种
考虑到迷宫是二维矩阵的格式,可以定该方案作为最短路径的搜素方案
方向问题:没有定义四方向还是八方向,已四方向为例
2.思路:
1.几个想法
1.正常而言,门视作可通行点,但前提是到达门时手上需要有钥匙
2.不存在先找到门,再去找钥匙的情况,路上来回的操作必定导致路径的延长
综述:进行搜索时,若遇到钥匙,则需记录已经取得的钥匙,再遇到门时,如果手上已经有对应的钥匙了,则视作可通行点,否则视作墙
2.代码
class APoint {
//坐标x
x: number = -1;
//坐标y
y: number = -1;
//拥有钥匙
keys: any[] = []
//步长
step: number = 0;
//上一个点
lastPoint: APoint | undefined;
}
class Game {
public doMaze(mazes: any[][]) {
if (mazes.length == 0) {
console.error(`地图数据有误`)
return;
}
let startX: number = -1;
let startY: number = -1;
let endX: number = -1;
let endY: number = -1;
let closeMap: any[] = []
let rets: any[] = []
//遍历,确定起点和终点
for (let x = 0; x < mazes.length; x++) {
closeMap[x] = []
for (let y = 0; y < mazes[x].length; y++) {
if (mazes[x][y] == '2') {
startX = x
startY = y
}
if (mazes[x][y] == '3') {
endX = x
endY = y
}
closeMap[x][y] = 0
}
}
if (startX == -1 || startY == -1 || endX == -1 || endY == -1) {
console.error(`地图数据有误`)
return;
}
let width = mazes[0].length;
let height = mazes.length;
let opens: any[] = []
let point = new APoint()
point.x = startX;
point.y = startY;
point.keys = []
point.step = 1;
point.lastPoint = undefined;
opens.push(point)
let dirX = [0, 0, 1, -1]
let dirY = [1, -1, 0, 0]
while (opens.length) {
let pt: APoint = opens.shift()//取出距离最短的点
console.error("opes", pt)
for (let i = 0; i < 4; i++) {
let newPtx = pt.x + dirX[i];
let newPty = pt.y + dirY[i];
console.error(newPtx, newPty)
if (newPtx < 0 || newPtx >= width || newPty < 0 || newPty >= height) {
console.error("超出地图范围")
continue
}
if (closeMap[newPtx][newPty] == 1) {
console.error("已经访问过了")
continue
}
if (mazes[newPtx][newPty] == '1') {
console.log("是路")
let np = new APoint()
np.x = newPtx
np.y = newPty
np.keys = pt.keys
np.lastPoint = pt
np.step = pt.step + 1;
opens.push(np)
}
if (mazes[newPtx][newPty] == '0') {
console.error("是墙")
}
if (mazes[newPtx][newPty] >= 'a' && mazes[newPtx][newPty] <= 'z') {
console.log("是钥匙")
let np = new APoint()
np.x = newPtx
np.y = newPty
np.keys = pt.keys
np.keys.push(mazes[newPtx][newPty])//加入新钥匙
np.lastPoint = pt
np.step = pt.step + 1;
opens.push(np)
}
if (mazes[newPtx][newPty] >= 'A' && mazes[newPtx][newPty] <= 'Z') {
console.log("是门")
let bHasKey = false;
for (let key of pt.keys) {
//有门的情况下,判断有么有钥匙,有,通过,没有,视作墙
if ((mazes[newPtx][newPty].charCodeAt(0) + 32) == key.charCodeAt(0)) {
bHasKey = true;
break;
}
}
if (bHasKey) {
console.log("钥匙已经有了")
let np = new APoint()
np.x = newPtx
np.y = newPty
np.keys = pt.keys
np.lastPoint = pt
np.step = pt.step + 1;
opens.push(np)
} else {
console.error(`还没找到钥匙:${mazes[newPtx][newPty]}`)
continue
}
}
if (mazes[newPtx][newPty] == '3') {
console.log("到达终点", pt, pt.step + 1)
let np = new APoint()
np.x = newPtx
np.y = newPty
np.keys = pt.keys
np.lastPoint = pt
np.step = pt.step + 1;
rets.push(np)
break;
}
}
closeMap[pt.x][pt.y] = 1
opens.sort((a: APoint, b: APoint) => { return a.step - b.step })//排序
}
if (rets.length <= 0) {
console.error("找不到路径")
} else {
//既然是最短,可以把路径集合起来重新排序
rets.sort((a: APoint, b: APoint) => {
return a.step - b.step
})
let ret = rets.shift()//取出第一个
this.doPrintRet(ret)
}
}
public doPrintRet(ret: APoint) {
if (ret.lastPoint != undefined) {
this.doPrintRet(ret.lastPoint)
console.error(ret.x, ret.y, ret.step)
} else {
console.error(ret.x, ret.y, ret.step)
}
}
}
console.error("main strart")
let mazeArr = [
['0', '3', '0', '0', '0', '0', '0', '0', '0', '0'],
['0', '1', '0', '0', '0', '0', '0', '0', '0', '0'],
['0', '1', '1', '1', '1', '1', '0', '0', '0', '0'],
['0', '1', 'A', '1', '1', '1', '0', '0', '0', '0'],
['0', '1', '1', '0', '1', '1', '0', '0', '0', '0'],
['0', '1', '0', '0', '1', '1', '0', '0', '0', '0'],
['0', '0', '1', '1', 'a', '1', '0', '0', '0', '0'],
['0', '0', '1', '0', '0', '1', '0', '0', '0', '0'],
['0', '0', '1', '1', '1', '1', '0', '0', '0', '0'],
['0', '0', '1', '0', '0', '0', '0', '0', '0', '0'],
['0', '0', '2', '0', '0', '0', '0', '0', '0', '0'],
]
let g = new Game()
g.doMaze(mazeArr)
3.可能有为考虑完整的地方,待补充调整,emmm