7 Заключение
В ходе проделанной работы было разработано программное средство, реализующее классический вариант волнового алгоритма – алгоритм Ли, - включающее:
графический вывод всей необходимой информации;
работу алгоритма при разных ситуациях;
понятный пользователю интерфейс.
Конечная программа точно следует все правилам алгоритма, учитывая все возможные ситуации.
Конечной целью данной работы является освоение волнового алгоритма, его программная реализация для дальнейшего применения на практике.
8 Список использованных источников
1. Электронный ресурс Codenet. Url:-[www.codenet.ru/progs/alg/way.php]
2. Свободная электронная энциклопедия «Википедия». Url:- [http://ru.wikipedia.org/wiki/Волновой_алгоритм], Url:-[ http://ru.wikipedia.org/wiki/Поиск_пути]
Приложение А. Код программы
uses GraphABC, ABCSprites;
const
Nk = 50;
type
Box = record
x, y: integer;
index: byte;
end;
Wall = record
i, j: integer;
pic: SpriteABC;
end;
var
walls: array of Wall;
field: array [,] of Box;
field_pic: Picture;
background: Picture;
ball: SpriteABC;
current_i, current_j: integer;
finish: boolean;
Ni: integer;
procedure Main();
var
i,j: integer;
begin
Window.Title:='Волновой алгоритм (алгоритм Ли)';
Window.IsFixedSize:=true;
Window.Height:=572;
Window.Width:=800;
Window.CenterOnScreen();
SetBrushColor(clTransparent);
SetFontColor(clWhite);
SetFontSize(10);
field_pic.Draw(0,0);
SetLength(field,11,11);
for i:=0 to 10 do
for j:=0 to 10 do
field[i,j].index:=255;
for i:=1 to 9 do
for j:=1 to 9 do
begin
field[i,j].x:=12 + 61 * (j - 1);
field[i,j].y:=12 + 61 * (i - 1);
field[i,j].index:=254;
end;
ball:=new SpriteABC(field[5,5].x + 2, field[5,5].y + 2, 'ball.png');
current_i:=5;
current_j:=5;
field[5,5].index:=253;
end;
procedure Refresh_background();
begin
background.Draw(572,0);
TextOut(573,0,'"Пробел" - реорганизовать поле');
TextOut(573,30,'Стартовая позиция: ' + IntToStr(current_i) + ';' + IntToStr(current_j));
end;
procedure Init_field();
var
walls_number: integer;
i, j: integer;
begin
for i:=1 to 9 do
for j:=1 to 9 do
if field[i,j].index<>253 then
field[i,j].index:=254;
if Length(walls) <> 0 then
for i:=0 to Length(walls) - 1 do
walls[i].pic.Destroy;
walls_number:=random(10,40);
SetLength(walls, walls_number);
for i:=0 to length(walls) - 1 do
begin
repeat
walls[i].i:=random(1,9);
walls[i].j:=random(1,9);
until field[walls[i].i,walls[i].j].index=254;
field[walls[i].i,walls[i].j].index:=255;
walls[i].pic:=new SpriteABC(field[walls[i].i, walls[i].j].x, field[walls[i].i, walls[i].j].y,'wall.png');
end;
end;
procedure Create_front(i, j, idx: integer);
begin
if (i + 1 <= 9) and (i + 1 >= 1) and (j <= 9) and (j >= 1) then
begin
if field[i + 1,j].index = 254 then
begin
field[i + 1,j].index:=idx + 1;
TextOut(field[i + 1,j].x,field[i + 1,j].y,IntToStr(field[i + 1,j].index));
end;
if field[i + 1,j].index = 253 then
finish:=true;
end;
if (i - 1 <= 9) and (i - 1 >= 1) and (j <= 9) and (j >= 1) then
begin
if field[i - 1,j].index = 254 then
begin
field[i - 1,j].index:=idx + 1;
TextOut(field[i - 1,j].x,field[i - 1,j].y,IntToStr(field[i - 1,j].index));
end;
if field[i - 1,j].index = 253 then
finish:=true;
end;
if (i <= 9) and (i >= 1) and (j + 1 <= 9) and (j + 1 >= 1) then
begin
if field[i,j + 1].index = 254 then
begin
field[i,j + 1].index:=idx + 1;
TextOut(field[i,j + 1].x,field[i,j + 1].y,IntToStr(field[i,j + 1].index));
end;
if field[i,j + 1].index = 253 then
finish:=true;
end;
if (i <= 9) and (i >= 1) and (j - 1 <= 9) and (j - 1 >= 1) then
begin
if field[i,j - 1].index = 254 then
begin
field[i,j - 1].index:=idx + 1;
TextOut(field[i,j - 1].x,field[i,j - 1].y,IntToStr(field[i,j - 1].index));
end;
if field[i,j - 1].index = 253 then
finish:=true;
end;
end;
procedure Create_path();
var
minimum: Box;
i, j, i1, j1: integer;
begin
i:=current_i;
j:=current_j;
repeat
if (i + 1 <= 9) and (i + 1 >= 1) and (j <= 9) and (j >= 1) and (i - 1 <= 9) and (i - 1 >= 1) then
begin
if field[i + 1,j].index < field[i - 1,j].index then
begin
minimum:=field[i + 1,j];
i1:=i + 1;
j1:=j;
end
else
begin
minimum:=field[i - 1,j];
i1:=i - 1;
j1:=j;
end;
end;
if (i <= 9) and (i >= 1) and (j + 1 <= 9) and (j + 1 >= 1) then
if field[i,j + 1].index < minimum.index then
begin
minimum:=field[i,j + 1];
i1:=i;
j1:=j + 1;
end;
if (i <= 9) and (i >= 1) and (j - 1 <= 9) and (j - 1 >= 1) then
if field[i,j - 1].index < minimum.index then
begin
minimum:=field[i,j - 1];
i1:=i;
j1:=j - 1;
end;
Sleep(1000);
ball.MoveTo(minimum.x + 2,minimum.y + 2);
i:=i1;
j:=j1;
until (minimum.index = 0);
field[current_i,current_j].index:=254;
field[i1,j1].index:=253;
current_i:=i1;
current_j:=j1;
end;
procedure Create_wave();
var
i, j: integer;
begin
Ni:=0;
finish:=false;
repeat
for i:=1 to 9 do
for j:=1 to 9 do
if field[i,j].index = Ni then
Create_front(i,j,Ni);
Inc(Ni);
until (finish = true) or (Ni > Nk);
if Ni > Nk then
TextOut(573,60,'Пути нет')
else
begin
Create_path();
TextOut(573,60,'Конечная позиция: ' + IntToStr(current_i) + ';' + IntToStr(current_j));
TextOut(573,90,'Количество волн: ' + IntToStr(Ni));
end;
end;
procedure Update_field();
var
i, j: integer;
begin
for i:=1 to 9 do
for j:=1 to 9 do
if (field[i,j].index <> 255) and (field[i,j].index <> 253) and (field[i,j].index <> 0) then
field[i,j].index:=254;
end;
procedure MyKeyDown(key: integer);
begin
if key = VK_Space then
begin
field_pic.Draw(0,0);
Init_field();
end;
end;
procedure MyMouseDown(x,y,mousebutton: integer);
var
i,j: integer;
begin
if mousebutton = 1 then
begin
for i:=1 to 9 do
for j:=1 to 9 do
begin
if (x >= field[i,j].x) and (x <= field[i,j].x + 60) and (y >= field[i,j].y) and (y <= field[i,j].y + 60) then
if field[i,j].index = 254 then
begin
field[i,j].index:=0;
Update_field();
Refresh_background();
field_pic.Draw(0,0);
Create_wave();
if Ni > Nk then
field[i,j].index:=254;
exit;
end;
end;
end;
end;
begin
field_pic:=new Picture('field.png');
background:=new Picture('background.png');
Main();
Init_field();
Refresh_background();
OnKeyDown:=MyKeyDown;
OnMouseDown:=MyMouseDown;
end.