pascalabcnet/InstallerSamples/Algorithms/Recursion/Hanoi.pas

122 lines
3.2 KiB
ObjectPascal
Raw Permalink Normal View History

// Ханойские башни
2015-05-14 22:35:07 +03:00
uses GraphABC;
type
/// Тип диска
2015-05-14 22:35:07 +03:00
DiskType = record
/// Диаметр диска
2015-05-14 22:35:07 +03:00
Sz: integer;
/// Цвет диска
2015-05-14 22:35:07 +03:00
Color: GraphABC.Color;
end;
/// Тип массива дисков на стержне
2015-05-14 22:35:07 +03:00
DiskArr = array of DiskType;
const
/// Количество дисков
2015-05-14 22:35:07 +03:00
CountDisks = 8;
/// Высота диска
2015-05-14 22:35:07 +03:00
DiskHeight = 12;
/// Приращение ширины диска
2015-05-14 22:35:07 +03:00
DiskWidthDelta = 12;
h = CountDisks * DiskWidthDelta * 2 + 20;
/// y-координата основания пирамид дисков
2015-05-14 22:35:07 +03:00
y0 = DiskHeight * CountDisks + 80;
hh = 30;
/// x-координата первого стержня
2015-05-14 22:35:07 +03:00
x1 = h div 2 + hh;
/// x-координата второго стержня
2015-05-14 22:35:07 +03:00
x2 = x1 + h;
/// x-координата третьего стержня
2015-05-14 22:35:07 +03:00
x3 = x2 + h;
/// Пауза, мс
2015-05-14 22:35:07 +03:00
delay = 50;
var
/// Массив пирамид дисков
2015-05-14 22:35:07 +03:00
Tower: array [1..3] of DiskArr;
/// Массив количеств дисков в пирамидах
2015-05-14 22:35:07 +03:00
DisksInTower: array [1..3] of integer;
/// Номер хода
2015-05-14 22:35:07 +03:00
MoveNumber: integer;
/// Рисование пирамиды
2015-05-14 22:35:07 +03:00
procedure DrawTower(a: DiskArr; n: integer; x0,y0: integer);
begin
Brush.Color := clBlack;
Rectangle(x0-5,y0,x0+5,y0-DiskHeight*CountDisks-10);
for var i:=0 to n-1 do
begin
Brush.Color := a[i].Color;
Rectangle(x0-a[i].sz*DiskWidthDelta,y0-DiskHeight*(i-1),x0+a[i].sz*DiskWidthDelta,y0-DiskHeight*i+1)
end;
end;
/// Рисование всех пирамид и информационной строки
2015-05-14 22:35:07 +03:00
procedure DrawAll;
begin
DrawTower(Tower[1],DisksInTower[1],x1,y0);
DrawTower(Tower[2],DisksInTower[2],x2,y0);
DrawTower(Tower[3],DisksInTower[3],x3,y0);
Brush.Color := clWhite;
TextOut(20,20,'Число перемещений дисков = '+MoveNumber);
2015-05-14 22:35:07 +03:00
Redraw;
end;
/// Перемещение диска со стержня FromN на стержень ToN
2015-05-14 22:35:07 +03:00
procedure MoveDisk(FromN, ToN: integer);
begin
Inc(MoveNumber);
Inc(DisksInTower[ToN]);
Tower[ToN][DisksInTower[ToN]-1] := Tower[FromN][DisksInTower[FromN]-1];
Dec(DisksInTower[FromN]);
Sleep(delay);
ClearWindow;
DrawAll;
end;
/// Основная екурсивная процедура алгоритма "Ханойские башни"
2015-05-14 22:35:07 +03:00
procedure MoveTower(n: integer; FromN, ToN, WorkN: integer);
begin
if n=0 then exit;
MoveTower(n-1, FromN, WorkN, ToN);
MoveDisk(FromN, ToN);
MoveTower(n-1, WorkN, ToN, FromN);
end;
/// Инициализация массивов
2015-05-14 22:35:07 +03:00
procedure InitTowers;
begin
SetLength(Tower[1],CountDisks);
SetLength(Tower[2],CountDisks);
SetLength(Tower[3],CountDisks);
DisksInTower[1] := CountDisks;
DisksInTower[2] := 0;
DisksInTower[3] := 0;
for var i:=0 to DisksInTower[1]-1 do
begin
Tower[1][i].Sz := DisksInTower[1]-i+1;
Tower[1][i].Color := clRandom;
end;
end;
/// Инициализация окна
2015-05-14 22:35:07 +03:00
procedure InitWindow;
begin
SetWindowSize(x3+x1,y0+50);
CenterWindow;
Window.Title := 'Ханойские башни';
2015-05-14 22:35:07 +03:00
Font.Size := 14;
Font.Name := 'Arial';
end;
begin
InitWindow;
InitTowers;
LockDrawing;
DrawAll;
MoveTower(CountDisks,1,3,2);
end.