Nadesłany przez Michał Knasiecki, 01 sierpnia 2005 01:00
Kod przedstawiony poniżej przedstawia główną część rozwiązania problemu.Pobierz pełne rozwiązanie.
Jeżeli nie odpowiada Ci sposób formatowania kodu przez autora skorzystaj z pretty printer'a i dostosuj go automatycznie do siebie.
Labirynt/Unit1.pas:
//Program zostal pobrany ze strony www.algorytm.org //Znajdziesz tam dużo iekawych algorytmów oraz struktór danych wraz //z dokladnym opisem i przykladowymi programami //Program opracowal Michal Knasiecki //************************************************************************* //UWAGA! //Format pliku z labiryntem: tablica rozmiaru 10*10, //Spacja oznacza wolne przejscie a znak "x" cegielke. Zobacz przykladowe pliki unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, StdCtrls; type TForm1 = class(TForm) Button1: TButton; Button2: TButton; PaintBox1: TPaintBox; Bevel1: TBevel; OpenDialog1: TOpenDialog; procedure Button1Click(Sender: TObject); procedure PaintBox1Paint(Sender: TObject); procedure FormActivate(Sender: TObject); procedure Button2Click(Sender: TObject); private { Private declarations } public { Public declarations } end; Type //Typ wykorzystywany w obsludze kolejki wskaznik_kolejki=^skladnik_kolejki; skladnik_kolejki=record odl:integer; xpos:integer; ypos:integer; wskaznik:wskaznik_kolejki; end; var Form1: TForm1; labirynt:array[1..10,1..10]of integer; wejscie,wyjscie:record x,y:integer; end; koniec_kolejki,poczatek_kolejki:wskaznik_kolejki; //Deklaracja procedur obslugi kolejki zawartych w bibliotece DLL //Nieskompilowana wersja procedur znajduje się w pliku Queue.DPR procedure DodajPunkt(var odl_,xpos_,ypos_:integer; var koniec_kolejki:wskaznik_kolejki);external 'Queue.Dll'; procedure UsunPunkt(var odl_,xpos_,ypos_:integer; var poczatek_kolejki:wskaznik_kolejki);external 'Queue.Dll'; implementation {$R *.DFM} procedure rysuj_labirynt;//Na podstawie tablicy procedura ta rysuje labirynt var i,j:byte; begin for i:=1 to 10 do for j:=1 to 10 do begin //ustalanie koloru cegielek if labirynt[i,j]=-1 then form1.paintbox1.canvas.brush.color:=clnavy else form1.paintbox1.canvas.brush.color:=clwhite; //rysowanie cegielek form1.PaintBox1.Canvas.Rectangle(i*10-10,j*10-10,i*10,j*10); end; end; procedure TForm1.Button1Click(Sender: TObject); var f:textfile; c:char; i,j:byte; begin if opendialog1.execute then //Wczytaj labirynt begin assignfile(f,opendialog1.filename); reset(f); for i:=1 to 10 do begin for j:=1 to 10 do begin read(f,c); if c='x' then labirynt[j,i]:=-1 else labirynt[j,i]:=0; end; readln(f); end; closefile(f); rysuj_labirynt; button2.enabled:=true;//Odblokowanie przycisku "Znajdź" end; end; procedure TForm1.PaintBox1Paint(Sender: TObject); begin rysuj_labirynt; end; procedure TForm1.FormActivate(Sender: TObject); begin form1.PaintBox1.Canvas.Pen.color:=clwhite; end; procedure Znajdz_We_Wy;//Procedura znajduje wejscie i wyjscie z labiryntu na jego brzegach var i:byte; begin wejscie.x:=0; wejscie.y:=0; wyjscie.x:=0; wyjscie.y:=0; //Sprawdzanie pierwszego rzędu for i:=1 to 10 do if labirynt[i,1]=0 then begin if wejscie.x=0 then begin wejscie.x:=i; wejscie.y:=1; end else begin wyjscie.x:=i; wyjscie.y:=1; end; end; //Sprawdzanie ostatniego rzędu for i:=1 to 10 do if labirynt[i,10]=0 then begin if wejscie.x=0 then begin wejscie.x:=i; wejscie.y:=10; end else begin wyjscie.x:=i; wyjscie.y:=10; end; end; //Sprawdzanie pierwszej kolumny for i:=1 to 10 do if labirynt[1,i]=0 then begin if wejscie.x=0 then begin wejscie.x:=1; wejscie.y:=i; end else begin wyjscie.x:=1; wyjscie.y:=i; end; end; //Sprawdzanie ostatniej kolumny for i:=1 to 10 do if labirynt[10,i]=0 then begin if wejscie.x=0 then begin wejscie.x:=10; wejscie.y:=i; end else begin wyjscie.x:=10; wyjscie.y:=i; end; end; //Uwaga: Zakladam, że w naszym labiryncie jest dokladnie 1 wescie i 1 wyjscie!!! //Radzę dopisac jeszcze fragment kodu, który sprawdza, czy w labiryncie //nie ma więcej wejsc i wyjsc. end; procedure Gdzie_Isc(x,y:byte;out up,dn,left,right:boolean); //Procedura ta sprawdza, w jakich kierunkach można isc z punktu (x,y) begin up:=false; dn:=false; left:=false; right:=false; if labirynt[x+1,y]=0 then right:=true; if labirynt[x-1,y]=0 then left:=true; if labirynt[x,y+1]=0 then dn:=true; if labirynt[x,y-1]=0 then up:=true; end; procedure Rysuj_Droge(var l:integer); var x,y:integer; i:integer; begin x:=Wyjscie.x; y:=Wyjscie.y; form1.paintbox1.canvas.brush.color:=clgreen; for i:=l+1 downto 1 do begin if labirynt[x-1,y]=i-1 then dec(x); if labirynt[x+1,y]=i-1 then inc(x); if labirynt[x,y-1]=i-1 then dec(y); if labirynt[x,y+1]=i-1 then inc(y); form1.paintbox1.canvas.ellipse(x*10-10,y*10-10,x*10,y*10); end; end; procedure TForm1.Button2Click(Sender: TObject); var up,dn,lt,rt,koniec:boolean; licznik:integer; x_pos,y_pos,x,y:integer; begin Znajdz_We_Wy; //Ustalanie wspólrzędnych wejscia i wyjscia. licznik:=1; koniec_kolejki:=nil; poczatek_kolejki:=nil; dodajpunkt(licznik,wejscie.x,wejscie.y,koniec_kolejki); poczatek_kolejki:=koniec_kolejki; koniec:=false; repeat usunpunkt(licznik,x_pos,y_pos,poczatek_kolejki); Gdzie_Isc(x_pos,y_pos,up,dn,lt,rt); if dn=true then begin y:=y_pos+1; x:=x_pos; inc(licznik); labirynt[x,y]:=licznik; dodajpunkt(licznik,x,y,koniec_kolejki); if poczatek_kolejki=nil then poczatek_kolejki:=koniec_kolejki; end; if up=true then begin y:=y_pos-1; x:=x_pos; inc(licznik); labirynt[x,y]:=licznik; dodajpunkt(licznik,x,y,koniec_kolejki); if poczatek_kolejki=nil then poczatek_kolejki:=koniec_kolejki; end; if lt=true then begin y:=y_pos; x:=x_pos-1; inc(licznik); labirynt[x,y]:=licznik; dodajpunkt(licznik,x,y,koniec_kolejki); if poczatek_kolejki=nil then poczatek_kolejki:=koniec_kolejki; end; if rt=true then begin y:=y_pos; x:=x_pos+1; inc(licznik); labirynt[x,y]:=licznik; dodajpunkt(licznik,x,y,koniec_kolejki); if poczatek_kolejki=nil then poczatek_kolejki:=koniec_kolejki; end; if (x=Wyjscie.x)and(y=Wyjscie.y)then koniec:=true; until (koniec); rysuj_droge(licznik); end; end.
Labirynt/Queue.dpr:
library Queue; uses SysUtils, Classes; Type wskaznik_kolejki=^skladnik_kolejki; skladnik_kolejki=record odl:integer; xpos:integer; ypos:integer; wskaznik:wskaznik_kolejki; end; {$R *.RES} procedure DodajPunkt(var odl_,xpos_,ypos_:integer;var koniec_kolejki:wskaznik_kolejki); var punkt:wskaznik_kolejki; begin punkt:=koniec_kolejki; new(koniec_kolejki); with koniec_kolejki^ do begin odl:=odl_; xpos:=xpos_; ypos:=ypos_; wskaznik:=nil end; if punkt<>nil then punkt^.wskaznik:=koniec_kolejki; end; Procedure UsunPunkt(var odl_,xpos_,ypos_:integer;var poczatek_kolejki:wskaznik_kolejki); var punkt:wskaznik_kolejki; begin if poczatek_kolejki<>nil then begin with poczatek_kolejki^ do begin odl_:=odl; xpos_:=xpos; ypos_:=ypos; punkt:=wskaznik; end; dispose(poczatek_kolejki); poczatek_kolejki:=punkt; end; end; exports dodajpunkt, usunpunkt; begin end.