Re: Обход доски шахматным конем
- From
- Dmitriy K. ()
- To
- Roman Zhelnov
- Date
- 2002-07-22T15:59:08Z
- Area
- RU.ALGORITHMS
From: "Dmitriy K." <krylov@mail.primorye.ru>
Привет.
"Roman Zhelnov" <Roman.Zhelnov@p29.f25.n5053.z2.fidonet.org>
сообщил/сообщила в новостях следующее:
news:1027250589@p29.f25.n5053.z2.FIDOnet.ftn...
>
> [√] Привет, как жизнь, All ?
>
> Интересует алгоритм обхода доски шахматным конем. На одну клетку можно
> вставать только один раз...
На - другую - тоже один раз, на третью - один раз и т.д. Рекурсия!
----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----
program MoveOfTheKnight;
const
DeskSize = 8; { Размер доски }
type
TCoords = 1..DeskSize; { возможные координаты доски }
TDesk = array[TCoords, TCoords] of Boolean; { Доски. Клетка либо пройдена,
либо нет }
TMove = record { ход }
X: TCoords;
Y: TCoords;
end;
const
NumOfKnightSteps = 8; { количество шагов конем из некоторого положения }
type
TKnightSteps = 1..NumOfKnightSteps;
const
KnightSteps: array[TKnightSteps] of record
DeltaX, DeltaY: Shortint
end = (
(DeltaX: -1; DeltaY: -2),
(DeltaX: 1; DeltaY: -2),
(DeltaX: 2; DeltaY: -1),
(DeltaX: 2; DeltaY: 1),
(DeltaX: -1; DeltaY: 2),
(DeltaX: 1; DeltaY: 2),
(DeltaX: -2; DeltaY: -1),
(DeltaX: -2; DeltaY: 1));
var
Desk: TDesk; { Доска }
MakedMoves: Integer; { Количество сделанных конем ходов }
const
MaxMoves = DeskSize * DeskSize; { Максимальное количество ходов }
var
Moves: array[1..MaxMoves] of TMove;
////////////////////////////////////////////////////////////////////////////
procedure PrintMoves; forward; { Вывод на экран результатов }
{ перемещение коня }
{ на входе: Pos - текущая позиция коня }
procedure Go(X, Y: TCoords);
var
i: TKnightSteps;
NewX, NewY: Shortint;
begin
{ Помечаем позицию, в которую пришли }
{ Writeln(MakedMoves); }
Desk[X, Y] := True;
Inc(MakedMoves);
Moves[MakedMoves].X := X;
Moves[MakedMoves].Y := Y;
if MakedMoves = MaxMoves then
PrintMoves { Ну вот, обшагали всю доску, результаты - на экран }
else
begin
{ Пытаемся найти подходящий ход }
for i := 1 to NumOfKnightSteps do
begin
{ Вычисление очередных координат }
NewX := X + KnightSteps[i].DeltaX;
if (NewX < 1) or (NewX > DeskSize) then Continue; { Выход за границы
доски - пропускаем }
NewY := Y + KnightSteps[i].DeltaY;
if (NewY < 1) or (NewY > DeskSize) then Continue; { Выход за границы
доски - пропускаем }
if not(Desk[NewX, NewY]) then Go(NewX, NewY); { Место не занято -
ходим туда }
end; { for... }
end; { if... }
{ Откат - помечаем позицию как непройденную }
Desk[X, Y] := False;
Dec(MakedMoves);
end;
procedure PrintMoves; { Вывод на экран результатов }
var
i: Integer;
begin
for i := 1 to MaxMoves do
with Moves[i] do
Write(X, ',', Y, '; ');
Writeln;
Writeln;
end;
begin
{ Обнулирование ;-) }
FillChar(Desk, SizeOf(Desk), 0);
MakedMoves := 0;
Go(1, 1);
WriteLn('Any Enter to continue...'); ReadLn;
end.
----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----
Для случая 3x3 и необходимости обойти все поля, кроме центрального,
программка работает на ура.
Естественно, можно оптимизировать. Например, конь сделает только 64 хода,
так что можно избежать рекурсии, а сделать итерацию; посмотреть, как он
обходит и т.д.
Еще можно использовать факт симметрии доски и ходов - например, за один шаг
рекурсии делать не один шаг конем а все восемь в доступных направлениях.
>
> [√] Пока, All, счастливого тебе коннекта ! ...
Та же фигня.
--
Отправлено через сервер Форумы@mail.ru - http://talk.mail.ru
--- ifmail v.2.15dev5
* Origin: Talk.Mail.Ru (2:5020/400)