2019-01-01 14:15:29 +03:00
|
|
|
|
// Ханойские башни
|
2015-05-14 22:35:07 +03:00
|
|
|
|
uses GraphABC;
|
|
|
|
|
|
|
|
|
|
|
|
type
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Тип диска
|
2015-05-14 22:35:07 +03:00
|
|
|
|
DiskType = record
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Диаметр диска
|
2015-05-14 22:35:07 +03:00
|
|
|
|
Sz: integer;
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Цвет диска
|
2015-05-14 22:35:07 +03:00
|
|
|
|
Color: GraphABC.Color;
|
|
|
|
|
|
end;
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Тип массива дисков на стержне
|
2015-05-14 22:35:07 +03:00
|
|
|
|
DiskArr = array of DiskType;
|
|
|
|
|
|
|
|
|
|
|
|
const
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Количество дисков
|
2015-05-14 22:35:07 +03:00
|
|
|
|
CountDisks = 8;
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Высота диска
|
2015-05-14 22:35:07 +03:00
|
|
|
|
DiskHeight = 12;
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Приращение ширины диска
|
2015-05-14 22:35:07 +03:00
|
|
|
|
DiskWidthDelta = 12;
|
|
|
|
|
|
h = CountDisks * DiskWidthDelta * 2 + 20;
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// y-координата основания пирамид дисков
|
2015-05-14 22:35:07 +03:00
|
|
|
|
y0 = DiskHeight * CountDisks + 80;
|
|
|
|
|
|
hh = 30;
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// x-координата первого стержня
|
2015-05-14 22:35:07 +03:00
|
|
|
|
x1 = h div 2 + hh;
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// x-координата второго стержня
|
2015-05-14 22:35:07 +03:00
|
|
|
|
x2 = x1 + h;
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// x-координата третьего стержня
|
2015-05-14 22:35:07 +03:00
|
|
|
|
x3 = x2 + h;
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Пауза, мс
|
2015-05-14 22:35:07 +03:00
|
|
|
|
delay = 50;
|
|
|
|
|
|
|
|
|
|
|
|
var
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Массив пирамид дисков
|
2015-05-14 22:35:07 +03:00
|
|
|
|
Tower: array [1..3] of DiskArr;
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Массив количеств дисков в пирамидах
|
2015-05-14 22:35:07 +03:00
|
|
|
|
DisksInTower: array [1..3] of integer;
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Номер хода
|
2015-05-14 22:35:07 +03:00
|
|
|
|
MoveNumber: integer;
|
|
|
|
|
|
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Рисование пирамиды
|
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-12-28 14:25:15 +03:00
|
|
|
|
/// Рисование всех пирамид и информационной строки
|
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;
|
2019-01-01 14:15:29 +03:00
|
|
|
|
TextOut(20,20,'Число перемещений дисков = '+MoveNumber);
|
2015-05-14 22:35:07 +03:00
|
|
|
|
Redraw;
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Перемещение диска со стержня 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-12-28 14:25:15 +03:00
|
|
|
|
/// Основная екурсивная процедура алгоритма "Ханойские башни"
|
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-12-28 14:25:15 +03:00
|
|
|
|
/// Инициализация массивов
|
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-12-28 14:25:15 +03:00
|
|
|
|
/// Инициализация окна
|
2015-05-14 22:35:07 +03:00
|
|
|
|
procedure InitWindow;
|
|
|
|
|
|
begin
|
|
|
|
|
|
SetWindowSize(x3+x1,y0+50);
|
|
|
|
|
|
CenterWindow;
|
2015-12-28 14:25:15 +03:00
|
|
|
|
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.
|
|
|
|
|
|
|
|
|
|
|
|
|