Задача в текущем случае (небольшая плата с 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.
Идея заключается в следующем. Мы используем массив, представляющий плату. Каждая ячейка может быть установлена либо в 0 - начальную точку, либо на -1 - неизвестную/недоступную ячейку, либо на -2 - заблокированную ячейку. Все положительные числа представляют собой минимальные обороты, чтобы достичь текущей ячейки в начальной точке.
Позже мы проверяем, содержит ли ячейка цели большее число 0. Это означает, что король может перейти к ячейке назначения. Если это так, мы находим ячейки с порядковыми числами, следующими друг за другом от цели до начальной точки и представляем их в массиве решений.
Две дополнительные процедуры: BoardOutput
и OutputTurns
распечатать структуру Совета и принять решение на консоль.
Посмотрите алгоритм BFS, это был бы естественный способ решить эту проблему. – interjay