已知可走的路径坐标,不存在行动力的消耗
/**
* 相邻位置的偏移量 8个方位
* 左,左下,下,右下,右,右上,上,左上
* */
let NearGridOffsets = [-1, 99, 100, 101, 1, -99, -100, -101];
/* 可以行走的路径位置点(r,c,r,c...) */
let points = [
8,3,8,4,8,5,8,7,8,8,8,9,8,10,8,11,8,12,8,13,8,14,8,15,8,17,8,18,
8,19,8,20,8,21,8,22,8,23,8,24,8,25,8,26,8,27,
8,30,8,31,8,32,8,33,8,34,8,35,8,36,8,37,8,38,8,39,
9,4,9,7,9,12,9,13,9,14,9,15,9,16,9,17,9,18,9,19,9,20,9,21,9,22,9,23,9,24,9,25,
9,26,9,27,9,28,9,29,9,30,9,31,9,32,9,33,9,34,9,35,9,36,9,37,9,38,9,39,
10,4,10,5,10,6,10,7,10,8,10,9,10,10,10,11,10,12,10,13,10,14,10,15,10,16,10,17,10,18,
10,19,10,20,10,21,10,22,10,23,10,24,10,25,10,26,10,27,10,28,10,29,
10,30,10,31,10,32,10,33,10,34,10,35,10,36,10,38,10,39,
11,5,11,6,11,7,11,8,11,9,11,10,11,11,11,12,11,13,11,14,11,15,11,16,11,17,11,18,
11,19,11,27,11,28,11,29,11,30,11,31,11,32,11,33,11,34,11,35,11,36,11,38,11,39,
12,5,12,8,12,9,12,10,12,12,12,13,12,14,12,15,12,16,12,17,12,28,12,29,
12,30,12,31,12,32,12,33,12,34,12,35,12,36,12,37,
13,5,13,6,13,7,13,8,13,9,13,10,13,11,13,12,13,13,13,14,13,15,13,16,13,17,
13,28,13,29,13,30,13,31,13,32,13,33,13,34,13,35,13,36,13,37,13,38,
14,9,14,8,14,10,14,11,14,12,14,13,14,14,14,15,14,16,14,17,
14,28,14,29,14,30,14,31,14,32,14,33,14,34,14,35,14,36,14,37,14,38,
15,12,15,13,15,14,15,15,15,16,15,17,
15,28,15,29,15,30,15,31,15,32,15,33,15,34,15,35,
16,9,16,10,16,11,16,12,16,13,16,14,16,15,16,16,16,17,16,18,
16,19,16,27,16,28,16,29,16,30,16,31,16,32,16,35,16,36,16,37,
17,9,17,10,17,12,17,13,17,14,17,15,17,16,17,17,17,18,17,19,
17,20,17,21,17,22,17,23,17,24,17,25,17,26,17,27,17,28,17,29,
17,30,17,31,17,35,17,36,17,37,
18,10,18,12,18,13,18,14,18,15,18,16,18,17,18,18,18,19,
18,20,18,21,18,22,18,23,18,24,18,25,18,26,18,27,18,28,18,29,18,35,18,36,
19,24,20,23,20,24,20,25,
]
/** 位置转换(初始可以行走的点) */
let grids = {};
for(let i = 0;i < points.length;){
let rc = 0, r = 0, c = 0;
r = points[i];
c = points[i+1];
rc = r * 100 + c;
grids[rc] = {
rc : rc,
r : r,
c : c,
}
i += 2;
}
/**
* 是否是无效的点
*
* @param {*} rc
* @returns
*/
let isInvalidPoint = (rc)=>{
return !grids[rc];
}
/**
* 查找指定的点是否在列表中
*
* @param {*} ps 列表
* @param {*} rc 指定的点
* @returns
*/
let findPoint = (ps, rc)=>{
for(let key in ps){
if(ps[key].rc == rc){
return ps[key];
}
}
return null;
}
/**
* 计算两点之间的距离
*
* @param {*} p1
* @param {*} p2
*/
let distance = (p1, p2)=>{
let x1 = 0, y1 = 0;
if( p1 >= 1000){
x1 = p1 % 100;
y1 = Math.floor(p1 / 100);
}else{
x1 = p1 % 10;
y1 = Math.floor(p1 / 10);
if (y1 == 2 || y1 == 4){
x1 = x1 + 0.5
}
}
let x2 = 0, y2 = 0;
if (p2 >= 1000){
x2 = p2 % 100;
y2 = Math.floor(p2 / 100);
}
else{
x2 = p2 % 10;
y2 = Math.floor(p2 / 10);
if (y2 == 2 || y2 == 4){
x2 = x2 + 0.5
}
}
return Math.sqrt(Math.pow((x1-x2),2) + Math.pow((y1-y2),2));
}
/** 将点位按f值升序 */
let sortPointAsc = (ps)=>{
ps.sort((p1, p2)=>{
return p1.f - p2.f;
})
}
/**
* 找出路径
*
* @param {*} from
* @param {*} dest
*/
let findPath = (from,dest)=>{
if(from == dest){
return null;
}
// 目标值
let dp = null;
let rc = null;
let g = null;
let h = null;
let np = null;
// 开发列表
let opens = [
{
rc : from,
g : 0, // 当前节点到起始点的估计
h : null, // 当前点到终点的估计
f : 0,
from : null, // 该点的前一格点
wc : 0, // 已移动的格子数
}
]
// 关闭列表
let closes = [];
while(opens.length > 0){
let cp = opens[0];
// 获取附近的点
for (let key in NearGridOffsets){
let ofs = NearGridOffsets[key];
rc = cp.rc + ofs;
// 目标点
if (rc == dest){
dp = {rc : dest, from : cp, wc : cp.wc+1}
break;
}
// 是否存在该点,并且不在关闭列表中
if (!isInvalidPoint(rc) && !findPoint(closes,rc)){
// 到该点所需要的消耗值
g = distance(cp.rc,rc) + cp.g;
// 是否在开放列表中
np = findPoint(opens,rc);
if (np){
// 如果存在
// 比较f值
let f = np.h + g
// 当新的cp点到 rc 该点所f消耗少,把新的cp则替换之前的form点
if (f < np.f){
np.f = f
np.g = g
np.from = cp
}
}else{
// 不存在放入开放列表中
h = distance(rc, dest)
opens.push({
rc : rc,
g : g,
h : h,
f : g + h,
from : cp,
wc : cp.wc+1,
} )
}
}
}
// 找到了目标点
if(dp){
break;
}
// 将该点从开放列表中移除
opens.splice(0,1);
closes.push(cp);
sortPointAsc(opens)
}
if (dp == null){
return null;
}
// 路径
let path = [];
do{
path.push(dp.rc);
dp = dp.from;
}while(dp != null && dp.rc != from);
path.push(from);
path.reverse();
return path;
}
let path = findPath(803,1020);
console.log(path);