当前位置:网站首页>利用a*启发式搜索解决迷宫寻路问题
利用a*启发式搜索解决迷宫寻路问题
2022-07-24 05:00:00 【一路向前的小Q】
1、迷宫:#表示墙,.表示可走,a表示起点,b表示终点,自己随便标起点a终点b
前言
利用a+启发式搜索解决迷宫寻路问题
体验迷宫动态生成网站:迷宫寻路-a*算法

一、a+启发式搜索是什么?
见另一博主博文:
运用公式:f=g+h
f:从起点到当前节点的总花费价值,越小越好,数值为g+h
g:从起点到当前节点的实际花费价值,越小越好,一般设置权重,上下左右每走一次+10
h:当前节点到终点的预搜索花费价值,不考虑遮挡物的存在,一般用曼哈顿距离表示法
计算两点之间水平竖直的距离和,比如:当前(0,0),终点(4,4),则h=4+4=8
二、js代码全解,详细说明
1、迷宫:#表示墙,.表示可走,a表示起点,b表示终点,自己随便标起点a终点b
a . . . . # . . .
. . . # . . b . .
. . # # . . # # .2、输出所有最短路径(走斜角最短,也会输出不走斜角的最短情况)

3、代码
//设置迷宫
let maze = `
a . . . . # . . .
. . . # . . b . .
. . # # . . # # .
`.slice(1, -1).split('\n').map(e => e.split(' '))
let [n, m] = [maze.length, maze[0].length]
//初始化
let openlist = [];//待搜索队列
let closelist = [];//已搜索及墙队列
let start;//起始位置,以[x,y,父节点,g,h,f]表示,迷宫中的a处
let end;//结束位置,迷宫中的b处
//初始化将墙加入closelist队列
for (let i = 0; i < n; i++) {
for (let j = 0; j < m; j++) {
if (maze[i][j] === '#') {
closelist.push(node(i, j, null, 0, 0));
}
if (maze[i][j] === 'a') {
start = [i, j, 0, 0, 0, 0]
}
if (maze[i][j] === 'b') {
end = [i, j, 0, 0, 0, 0]
}
}
}
//生成节点函数,核心计算:f=g+h
function node(x, y, p, g, h) {
let f = g + h;
return [x, y, p, g, h, f];
}
//曼哈顿距离计算法,即计算两点之间水平竖直的距离和,不考虑墙,是估计距离
function mhd(x1, y1, x2, y2) {
return Math.abs(x1 - x2) + Math.abs(y1 - y2);
}
//扩散搜索函数【各方向价值计算判断,上下左右权重为10,加入待搜索队列】
function ks(arr = [0, 0, 0, 0, 0, 0]) {
let [x, y, p, g, h, f] = arr;
//将当前节点设置为父节点
let pp = arr;
//向下走,如果存在就g+10,加入待搜索队列
if (
x + 1 < n &&
!ph([x + 1, y], closelist)
) {
openlist.push(node(x + 1, y, pp, g + 10, mhd(x + 1, y, ...end)));
}
//向上走,如果存在就g+10,加入待搜索队列
if (
x - 1 >= 0 &&
!ph([x - 1, y], closelist)
) {
openlist.push(node(x - 1, y, pp, g + 10, mhd(x - 1, y, ...end)));
}
//向右走,如果存在就g+10,加入待搜索队列
if (
y + 1 < m &&
!ph([x, y + 1], closelist)
) {
openlist.push(node(x, y + 1, pp, g + 10, mhd(x, y + 1, ...end)));
}
//向左走,如果存在就g+10,加入待搜索队列
if (
y - 1 >= 0 &&
!ph([x, y - 1], closelist)
) {
openlist.push(node(x, y - 1, pp, g + 10, mhd(x, y - 1, ...end)));
}
//向左上角走,如果存在就g+14,加入待搜索队列,因为是斜角,勾股定理根号2约等于
if (
y - 1 >= 0 && x - 1 >= 0 &&
!ph([x - 1, y - 1], closelist)
) {
openlist.push(node(x - 1, y - 1, pp, g + 14, mhd(x - 1, y - 1, ...end)));
}
//向左下角走,如果存在就g+14,加入待搜索队列
if (
y - 1 >= 0 && x + 1 < n &&
!ph([x + 1, y - 1], closelist)
) {
openlist.push(node(x + 1, y - 1, pp, g + 14, mhd(x + 1, y - 1, ...end)));
}
//向右下角走,如果存在就g+14,加入待搜索队列
if (
y + 1 < m && x + 1 < n &&
!ph([x + 1, y + 1], closelist)
) {
openlist.push(node(x + 1, y + 1, pp, g + 14, mhd(x + 1, y + 1, ...end)));
}
//向右上角走,如果存在就g+14,加入待搜索队列
if (
y + 1 < m && x - 1 >= 0 &&
!ph([x - 1, y + 1], closelist)
) {
openlist.push(node(x - 1, y + 1, pp, g + 14, mhd(x - 1, y + 1, ...end)));
}
//如果超出迷宫范围,表示此路不通,加入待搜索队列进行识别回溯
if (x + 1 > n || y + 1 > m) {
openlist.push([-1, -1, -1, -1, -1, -1]);
}
}
//判断当前节点在不在closelist队列中,如果在就跳过
function ph(arr1, arr2) {
let fg = false;
for (let x of arr2) {
if (arr1[0] === x[0] && arr1[1] === x[1]) {
fg = true;
break;
}
}
return fg;
}
//每次收集除了当前最小的f的节点之外是所有其他不用的节点
let stk = [start]
//路径集合
let path = [];
//开始搜索
try {
while (stk.length > 0) {
//将起点加入待搜索队列
openlist.push(stk.shift());
while (1) {
//待搜索队列按f值大小排序
openlist.sort((a, b) => a[5] - b[5]);
//拿出当前openlist中排除f相同的最小的节点
let cur = openlist.shift();
//收集除了当前最小的f的节点之外的所有其他不用的节点,按f值排序,以便道路不通时重新寻路
stk = [...new Set([...stk, ...openlist].sort((a, b) => a[5] - b[5]))];
//判断最后能不能走通,如果当前节点返回-1,则走不通,拿出stk的最小值重新搜索
//console.log(cur)
if (cur[0] === -1) {
if (stk.length === 0) break
cur = stk.shift()
//重置搜索结果,过滤比当前cur的f大的节点,重新寻路
closelist = closelist.filter(e => e[5] < cur[5])
continue
}
//如果是普通节点,把当前节点放入已搜索队列
closelist.push(cur);
//判断当前节点是不是终点,如果不是重点就用扩散搜索函数扩散openlist
if (cur[0] === end[0] && cur[1] === end[1]) break;
ks(cur);
}
//把最后一次到重点的节点拿出来,因为每个节点都包含父节点(上一个节点,循环取父节点直至父节点为0)
//初始节点父节点设置成了0以便判断
let res = closelist.slice(-1)[0];
path.push([])
while (true) {
path[path.length - 1].push([res[0], res[1]]);
if (!res[2]) break;
res = res[2];
}
}
if (path.length > 0) {
console.log('最短路径:' + path[0].length + '步')
//因为节点是从终点开始回推找到起点的,所以要翻转一下路径顺序
path.map(e => e.reverse()).forEach((e, i) => {
console.log('路径' + (i + 1) + ':' + e.map(e => `(${e[0]},${e[1]})`).join('->'))
})
} else {
console.log('寻路失败请检查!')
}
} catch (err) {
if (path.length > 0) {
console.log('最短路径:' + path[0].length + '步')
//因为节点是从终点开始回推找到起点的,所以要翻转一下路径顺序
path.map(e => e.reverse()).forEach((e, i) => {
console.log('路径' + (i + 1) + ':' + e.map(e => `(${e[0]},${e[1]})`).join('->'))
})
} else {
console.log('寻路失败请检查!')
}
}
边栏推荐
- Chapter III encog workbench
- How to get the signature file of Baidu Post Bar? Baidu Post Bar signature file setting and use method graphic introduction
- 力扣146题:LRU缓存
- P一个配置文件期间将SDA松集成。支但事实上
- Face algorithms
- MySQL constraint_ Foreign key constraint
- Question 146: LRU cache
- Want to know how a C program is compiled—— Show you the compilation of the program
- How to make yourself look young in how old robot? How old do I look? Younger method skills
- Post SQL era: edgedb 2.0 Release Notice
猜你喜欢

Several common sorts

Merge sort

MapReduce concept

Sort - quicksort

激活函数和最常用的10个激活函数

How to solve the engine prompt alias herodb and game engine startup exceptions?
![[postgraduate entrance examination vocabulary training camp] day 10 - capital, expand, force, adapt, depand](/img/9a/a218c46806cf286f0518a72809e084.png)
[postgraduate entrance examination vocabulary training camp] day 10 - capital, expand, force, adapt, depand

Kingbase V8R6集群安装部署案例---脚本在线一键缩容

HMS core discovery Episode 16 live broadcast preview | play AI's new "sound" state with tiger pier

Kingbase v8r6 cluster installation and deployment case - script online one click expansion
随机推荐
Nautilus 3.19.2 adds momentum to Gnome
Little black leetcode journey: 100 same trees
Airiot Q & A issue 5 | how to use low code business flow engine?
Unable to delete the file prompt the solution that the file cannot be deleted because the specified file cannot be found
作、Ho量有关。嵌入,只有一70的该接
Baidu wallet helps you repay the inter-bank repayment of your credit card. The handling fee is 0. Newcomers who arrive in real time will be rewarded with 5 yuan
P一个配置文件期间将SDA松集成。支但事实上
Little black gnawing leetcode:589. Preorder traversal of n-ary tree
Recruitment | embedded software (MCU) Engineer
C language: bubble sorting
Transpose of array sparse matrix
A hospital call system based on C language
Quick reference manual for the strongest collation of common regular expressions (glory Collection Edition)
[Huang ah code] Introduction to MySQL - 3. I use select *, and the boss directly rushed me home by train, but I still bought a station ticket
Summary of the development process and key and difficult points of the Listening Project
Illustration and text demonstrate the movable range of the applet movable view
greatest common divisor
Gau and ppm for image semantic segmentation
[JDBC] error exception in thread "main" com.mysql.jdbc.exceptions.jdbc4.communicationsexception: communica
pycharm 调试功能介绍与使用