Algorithm A*/Dijkstra';s算法简单实现(Pascal)
我试图使用本文实现一个*路径查找算法(现在是Dijkstra算法,即没有启发式算法)。但我无法找出代码中的错误(它找到了错误的路径) 而不是空的开始。。。结束;这一步应该是: 如果已在打开列表中,请检查此路径是否指向该列表 以G成本作为衡量标准,正方形更好。较低的G成本意味着 这是一条更好的道路。如果是,请将正方形的父对象更改为 当前平方,并重新计算平方的G和F分数 但我认为这并不重要,因为没有对角线运动Algorithm A*/Dijkstra';s算法简单实现(Pascal),algorithm,pascal,path-finding,dijkstra,a-star,Algorithm,Pascal,Path Finding,Dijkstra,A Star,我试图使用本文实现一个*路径查找算法(现在是Dijkstra算法,即没有启发式算法)。但我无法找出代码中的错误(它找到了错误的路径) 而不是空的开始。。。结束;这一步应该是: 如果已在打开列表中,请检查此路径是否指向该列表 以G成本作为衡量标准,正方形更好。较低的G成本意味着 这是一条更好的道路。如果是,请将正方形的父对象更改为 当前平方,并重新计算平方的G和F分数 但我认为这并不重要,因为没有对角线运动 uses crt; const MAXX = 20; MAXY
uses
crt;
const
MAXX = 20;
MAXY = 25;
type
TArr = array [0..MAXY, 0..MAXX] of integer;
TCell = record
x: integer;
y: integer;
end;
TListCell = record
x: integer;
y: integer;
G: integer;
parent: TCell;
end;
TListArr = array [1..10000] of TListCell;
TList = record
arr: TListArr;
len: integer;
end;
var
i, j, minind, ind, c: integer;
start, finish: TCell;
current: TListCell;
field: TArr;
opened, closed: TList;
procedure ShowField;
var
i, j: integer;
begin
textcolor(15);
for i := 0 to MAXX do
begin
for j := 0 to MAXY do
begin
case field[j, i] of
99: textcolor(8); // not walkable
71: textcolor(14); // walkable
11: textcolor(10); // start
21: textcolor(12); // finish
15: textcolor(2); // path
14: textcolor(5);
16: textcolor(6);
end;
write(field[j, i], ' ');
end;
writeln;
end;
textcolor(15);
end;
procedure AddClosed(a: TListCell);
begin
closed.arr[closed.len + 1] := a;
inc(closed.len);
end;
procedure AddOpened(x, y, G: integer);
begin
opened.arr[opened.len + 1].x := x;
opened.arr[opened.len + 1].y := y;
opened.arr[opened.len + 1].G := G;
inc(opened.len);
end;
procedure DelOpened(n: integer);
var
i: integer;
begin
AddClosed(opened.arr[n]);
for i := n to opened.len - 1 do
opened.arr[i] := opened.arr[i + 1];
dec(opened.len);
end;
procedure SetParent(var a: TListCell; parx, pary: integer);
begin
a.parent.x := parx;
a.parent.y := pary;
end;
function GetMin(var a: TList): integer;
var
i, min, mini: integer;
begin
min := MaxInt;
mini := 0;
for i := 1 to a.len do
if a.arr[i].G < min then
begin
min := a.arr[i].G;
mini := i;
end;
GetMin := mini;
end;
function FindCell(a: TList; x, y: integer): integer;
var
i: integer;
begin
FindCell := 0;
for i := 1 to a.len do
if (a.arr[i].x = x) and (a.arr[i].y = y) then
begin
FindCell := i;
break;
end;
end;
procedure ProcessNeighbourCell(x, y: integer);
begin
if (field[current.x + x, current.y + y] <> 99) then // if walkable
if (FindCell(closed, current.x + x, current.y + y) <= 0) then // and not visited before
if (FindCell(opened, current.x + x, current.y + y) <= 0) then // and not added to list already
begin
AddOpened(current.x + x, current.y + y, current.G + 10);
SetParent(opened.arr[opened.len], current.x, current.y);
// field[opened.arr[opened.len].x, opened.arr[opened.len].y]:=16;
end
else
begin
end;
end;
begin
randomize;
for i := 0 to MAXX do
for j := 0 to MAXY do
field[j, i] := 99;
for i := 1 to MAXX - 1 do
for j := 1 to MAXY - 1 do
if random(5) mod 5 = 0 then
field[j, i] := 99
else field[j, i] := 71;
// start and finish positions coordinates
start.x := 5;
start.y := 3;
finish.x := 19;
finish.y := 16;
field[start.x, start.y] := 11;
field[finish.x, finish.y] := 21;
ShowField;
writeln;
opened.len := 0;
closed.len := 0;
AddOpened(start.x, start.y, 0);
SetParent(opened.arr[opened.len], -1, -1);
current.x := start.x;
current.y := start.y;
repeat
minind := GetMin(opened);
current.x := opened.arr[minind].x;
current.y := opened.arr[minind].y;
current.G := opened.arr[minind].G;
DelOpened(minind);
ProcessNeighbourCell(1, 0); // look at the cell to the right
ProcessNeighbourCell(-1, 0); // look at the cell to the left
ProcessNeighbourCell(0, 1); // look at the cell above
ProcessNeighbourCell(0, -1); // look at the cell below
if (FindCell(opened, finish.x, finish.y) > 0) then
break;
until opened.len = 0;
// count and mark path
c := 0;
while ((current.x <> start.x) or (current.y <> start.y)) do
begin
field[current.x, current.y] := 15;
ind := FindCell(closed, current.x, current.y);
current.x := closed.arr[ind].parent.x;
current.y := closed.arr[ind].parent.y;
inc(c);
end;
ShowField;
writeln(c);
readln;
end.
使用
阴极射线管;
常数
MAXX=20;
MAXY=25;
类型
TArr=整数的数组[0..MAXY,0..MAXX];
TCell=记录
x:整数;
y:整数;
结束;
TListCell=记录
x:整数;
y:整数;
G:整数;
家长:TCell;
结束;
TListArr=TListCell的数组[1..10000];
t列表=记录
arr:tlistar;
len:整数;
结束;
变量
i、 j,minind,ind,c:整数;
开始,结束:TCell;
电流:TListCell;
领域:塔尔;
打开、关闭:t列表;
程序展示区;
变量
i、 j:整数;
开始
textcolor(15);
对于i:=0到MAXX do
开始
对于j:=0到最大do
开始
案例域[j,i]的
99:textcolor(8);//不能行走
71:textcolor(14);//可行走
11:textcolor(10);//开始
21:textcolor(12);//完成
15:textcolor(2);//路径
14:textcolor(5);
16:textcolor(6);
结束;
写入(字段[j,i],“”);
结束;
书面语;
结束;
textcolor(15);
结束;
程序AddClosed(a:TListCell);
开始
closed.arr[closed.len+1]:=a;
公司(闭门造车),;
结束;
程序AddOpened(x,y,G:整数);
开始
opened.arr[opened.len+1].x:=x;
opened.arr[opened.len+1].y:=y;
opened.arr[opened.len+1].G:=G;
股份有限公司(公开发行);
结束;
程序去开放(n:整数);
变量
i:整数;
开始
AddClosed(opened.arr[n]);
对于i:=n到opened.len-1 do
opened.arr[i]:=opened.arr[i+1];
12月(开放时间:len);
结束;
过程SetParent(变量a:TListCell;parx,pary:integer);
开始
a、 parent.x:=parx;
a、 parent.y:=pary;
结束;
函数GetMin(var a:TList):整数;
变量
i、 最小值,最小值:整数;
开始
min:=MaxInt;
迷你:=0;
对于i:=1到a.len do
如果a.arr[i].G 如果(FindCell(closed,current.x+x,current.y+y)您发布了大量代码,您是否尝试过缩小失败的范围
你把你的代码和维基百科上的比较了吗
还要记住,dijkstra只是一个启发式为0的*
编辑:
您链接的文章(我现在意识到这与我学习A*时使用的文章非常相似,很有趣)包含了说明步骤。我建议您重新创建地图/网格并在其上运行您的实现。然后逐步浏览图片:
八个初始邻居是否已添加到打开列表中?它们是否具有正确的父级
是否根据启发式选择正确的打开节点作为下一个要扫描的节点
关闭节点的列表是否正确
等等
您应该重写程序,使用循环而不是剪切粘贴来访问每个邻居。如果这样做,您将避免如下错误:
if (field[current.x, current.y - 1] <> 99) then
if (FindCell(closed, current.x, current.y - 1) <= 0) then
if (FindCell(opened, current.x + 1, current.y) <= 0) then
如果你不写循环而只是重构
ProcessCell(x+1, y);
ProcessCell(x-1, y);
ProcessCell(x, y-1);
ProcessCell(x, y-1);
这也是一个很大的改进。失败==崩溃?程序工作正常,但路径不正确(例如上面的屏幕截图)。我不明白在我实现这个算法时哪里出错=\看起来像是在字段/坐标移动实现中的某个地方。这是个好主意,谢谢,我会重写它:)虽然修这条线并没有解决问题。但是你能解释一下“访问每个邻居的循环”是什么意思吗?它是不是类似于ProcessCell(x+1,y);过程细胞(X-1,y);过程细胞(x,y-1);过程细胞(x,y-1);而不是这些?@Alex11223注意,current.x+1
不一致性必须在程序中修复(至少)两次。我添加了更多关于代码结构的讨论。更新的代码,以及固定路径标记(应该有,或者改为和),看起来现在可以工作了:)
ProcessCell(x+1, y);
ProcessCell(x-1, y);
ProcessCell(x, y-1);
ProcessCell(x, y-1);