當前情況下的任務(僅包含64個單元的小板)可以按照以下方式在不遞歸的情況下解決。
Program ShortestPath;
type
TCoords = record
X, Y: byte;
end;
TBoardArray = array [0 .. 63] of TCoords;
var
Goal: TCoords;
Current: TCoords;
i, j: integer;
ArrBlocked, PathResult: TBoardArray;
BlockedCount: byte;
Board: array [1 .. 8, 1 .. 8] of integer;
procedure CountTurnsToCells;
var
Repetitions: byte;
BestPossible: byte;
begin
for Repetitions := 1 to 63 do
for j := 1 to 8 do
for i := 1 to 8 do
if Board[i, j] <> -2 then
begin
BestPossible := 255;
if (i < 8) and (Board[i + 1, j] >= 0) then
BestPossible := Board[i + 1, j] + 1;
if (j < 8) and (Board[i, j + 1] >= 0) and
(BestPossible > Board[i, j + 1] + 1) then
BestPossible := Board[i, j + 1] + 1;
if (i > 1) and (Board[i - 1, j] >= 0) and
(BestPossible > Board[i - 1, j] + 1) then
BestPossible := Board[i - 1, j] + 1;
if (j > 1) and (Board[i, j - 1] >= 0) and
(BestPossible > Board[i, j - 1] + 1) then
BestPossible := Board[i, j - 1] + 1;
{ diagonal }
if (j > 1) and (i > 1) and (Board[i - 1, j - 1] >= 0) and
(BestPossible > Board[i - 1, j - 1] + 1) then
BestPossible := Board[i - 1, j - 1] + 1;
if (j > 1) and (i < 8) and (Board[i + 1, j - 1] >= 0) and
(BestPossible > Board[i + 1, j - 1] + 1) then
BestPossible := Board[i + 1, j - 1] + 1;
if (j < 8) and (i < 8) and (Board[i + 1, j + 1] >= 0) and
(BestPossible > Board[i + 1, j + 1] + 1) then
BestPossible := Board[i + 1, j + 1] + 1;
if (j < 8) and (i > 1) and (Board[i - 1, j + 1] >= 0) and
(BestPossible > Board[i - 1, j + 1] + 1) then
BestPossible := Board[i - 1, j + 1] + 1;
if (BestPossible < 255) and
((Board[i, j] = -1) or (Board[i, j] > BestPossible)) then
Board[i, j] := BestPossible;
end;
end;
function GetPath: TBoardArray;
var
n, TurnsNeeded: byte;
NextCoord: TCoords;
function FindNext(CurrentCoord: TCoords): TCoords;
begin
result.X := 0;
result.Y := 0;
if (CurrentCoord.X > 1) and (Board[CurrentCoord.X - 1, CurrentCoord.Y] >= 0)
and (Board[CurrentCoord.X - 1, CurrentCoord.Y] < Board[CurrentCoord.X,
CurrentCoord.Y]) then
begin
result.X := CurrentCoord.X - 1;
result.Y := CurrentCoord.Y;
exit;
end;
if (CurrentCoord.Y > 1) and (Board[CurrentCoord.X, CurrentCoord.Y - 1] >= 0)
and (Board[CurrentCoord.X, CurrentCoord.Y - 1] < Board[CurrentCoord.X,
CurrentCoord.Y]) then
begin
result.X := CurrentCoord.X;
result.Y := CurrentCoord.Y - 1;
exit;
end;
if (CurrentCoord.X < 8) and (Board[CurrentCoord.X + 1, CurrentCoord.Y] >= 0)
and (Board[CurrentCoord.X + 1, CurrentCoord.Y] < Board[CurrentCoord.X,
CurrentCoord.Y]) then
begin
result.X := CurrentCoord.X + 1;
result.Y := CurrentCoord.Y;
exit;
end;
if (CurrentCoord.Y < 8) and (Board[CurrentCoord.X, CurrentCoord.Y + 1] >= 0)
and (Board[CurrentCoord.X, CurrentCoord.Y + 1] < Board[CurrentCoord.X,
CurrentCoord.Y]) then
begin
result.X := CurrentCoord.X;
result.Y := CurrentCoord.Y + 1;
exit;
end;
{ diagonal }
if (CurrentCoord.X > 1) and (CurrentCoord.Y > 1) and
(Board[CurrentCoord.X - 1, CurrentCoord.Y-1] >= 0) and
(Board[CurrentCoord.X - 1, CurrentCoord.Y-1] < Board[CurrentCoord.X,
CurrentCoord.Y]) then
begin
result.X := CurrentCoord.X - 1;
result.Y := CurrentCoord.Y - 1;
exit;
end;
if (CurrentCoord.X < 8) and (CurrentCoord.Y > 1) and
(Board[CurrentCoord.X + 1, CurrentCoord.Y-1] >= 0) and
(Board[CurrentCoord.X + 1, CurrentCoord.Y-1] < Board[CurrentCoord.X,
CurrentCoord.Y]) then
begin
result.X := CurrentCoord.X + 1;
result.Y := CurrentCoord.Y - 1;
exit;
end;
if (CurrentCoord.X < 8) and (CurrentCoord.Y < 8) and
(Board[CurrentCoord.X + 1, CurrentCoord.Y+1] >= 0) and
(Board[CurrentCoord.X + 1, CurrentCoord.Y+1] < Board[CurrentCoord.X,
CurrentCoord.Y]) then
begin
result.X := CurrentCoord.X + 1;
result.Y := CurrentCoord.Y + 1;
exit;
end;
if (CurrentCoord.X > 1) and (CurrentCoord.Y < 8) and
(Board[CurrentCoord.X - 1, CurrentCoord.Y+1] >= 0) and
(Board[CurrentCoord.X - 1, CurrentCoord.Y+1] < Board[CurrentCoord.X,
CurrentCoord.Y]) then
begin
result.X := CurrentCoord.X - 1;
result.Y := CurrentCoord.Y + 1;
exit;
end;
end;
begin
TurnsNeeded := Board[Goal.X, Goal.Y];
NextCoord := Goal;
for n := TurnsNeeded downto 1 do
begin
result[n] := NextCoord;
NextCoord := FindNext(NextCoord);
end;
result[0] := NextCoord; // starting position
end;
procedure BoardOutput;
begin
for j := 1 to 8 do
for i := 1 to 8 do
if i = 8 then
writeln(Board[i, j]:2)
else
write(Board[i, j]:2);
end;
procedure OutputTurns;
begin
writeln(' X Y');
for i := 0 to Board[Goal.X, Goal.Y] do
writeln(PathResult[i].X:2, PathResult[i].Y:2)
end;
begin
{ test values }
Current.X := 2;
Current.Y := 5;
Goal.X := 8;
Goal.Y := 7;
ArrBlocked[0].X := 4;
ArrBlocked[0].Y := 3;
ArrBlocked[1].X := 2;
ArrBlocked[1].Y := 2;
ArrBlocked[2].X := 8;
ArrBlocked[2].Y := 5;
ArrBlocked[3].X := 7;
ArrBlocked[3].Y := 6;
BlockedCount := 4;
{ preparing the board }
for j := 1 to 8 do
for i := 1 to 8 do
Board[i, j] := -1;
for i := 0 to BlockedCount - 1 do
Board[ArrBlocked[i].X, ArrBlocked[i].Y] := -2; // the blocked cells
Board[Current.X, Current.Y] := 0; // set the starting position
CountTurnsToCells;
BoardOutput;
if Board[Goal.X, Goal.Y] < 0 then
writeln('no path') { there is no path }
else
begin
PathResult := GetPath;
writeln;
OutputTurns
end;
readln;
end.
ideea是以下內容。我們使用代表董事會的數組。每個單元格可以設置爲0 - 起始點,可以是-1 - 未知/無法訪問的單元格,也可以設置爲-2 - 阻止的單元格。所有正數表示從起點到達當前單元的最小轉數。
稍後我們檢查目標單元格是否包含大於0的數字。這表示國王可以移動到目標單元格。如果是這樣,我們從目標到起點找到序數相同的單元格,並將它們表示在決策數組中。
這兩個附加程序:BoardOutput
和OutputTurns
將控制檯的結構和決定打印出來。
查找BFS算法,這將是解決這個問題的自然方法。 – interjay