Fora kod upisivanja podataka ciju velicinu ne znate prilikom kompajliranja programa je da pre podatka upisete i njegovu velicinu. Tako ce kod koji bude citao podatke znati koliko mesta je potrebno da bi se podatak uspesno ucitao.
Evo kako sam napisao funkcije za snimanje i ucitavanje soba:
Code:
const
// Header fajla u kojem se snimaju sobe (ROOM)
CROOM_HEADER = $4D4F4F52;
// Ucitavanje soba iz fajla
function LoadRooms(FileName: String; var Rooms: TRooms): Integer;
var
HFile: File;
begin
// Pretpostavimo da ce doci do greske
Result := -1;
// Otvaramo fajl
Assign(HFile, FileName);
try
Reset(HFile, 1);
// Ucitaj iz fajla
Result := LoadRooms(HFile, Rooms);
finally
// Zatvori fajl
Close(HFile);
end;
end;
function LoadRooms(var HFile: File; var Rooms: TRooms): Integer; overload;
var
Header: Cardinal;
// Broj fajlova procitanih iz fajla
ReadCount: Cardinal;
Count: Integer;
I: Integer;
Len: Integer;
begin
// Pretpostavimo da ce doci do greske
Result := -1;
// Ucitavanje headera
BlockRead(HFile, Header, SizeOf(Header), ReadCount);
if (ReadCount <> SizeOf(Header)) or (Header <> CROOM_HEADER) then
Exit;
// Citamo broj soba
BlockRead(HFile, Count, SizeOf(Count), ReadCount);
if ReadCount <> SizeOf(Count) then
Exit;
// Postavljamo velicinu niza
SetLength(Rooms, Count);
// Ucitavanje soba
for I := 0 to Count - 1 do
begin
// Citamo duzinu opisa
BlockRead(HFile, Len, SizeOf(Len), ReadCount);
if ReadCount <> SizeOf(Len) then
Exit;
// Postavljamo duzinu opisa
SetLength(Rooms[I].Decription, Len);
// Citamo opis sobe
BlockRead(HFile, Rooms[I].Decription[1], Len, ReadCount);
if ReadCount <> Len then
Exit;
// Citamo prolaze do drugih soba
BlockRead(HFile, Rooms[I].Doors, SizeOf(Rooms[I].Doors), ReadCount);
if ReadCount <> SizeOf(Rooms[I].Doors) then
Exit;
end;
// Sve je uspesno zavrseno
Result := Count;
end;
// Snimanje soba u fajl
function SaveRooms(FileName: String; var Rooms: TRooms; Count: Integer): Integer; overload;
var
HFile: File;
begin
// Pretpostavimo da ce doci do greske
Result := -1;
// Otvaramo fajl
Assign(HFile, FileName);
try
Rewrite(HFile, 1);
// Snimi u fajl
Result := SaveRooms(HFile, Rooms, Count);
finally
// Zatvori fajl
Close(HFile);
end;
end;
function SaveRooms(var HFile: File; var Rooms: TRooms; Count: Integer): Integer; overload;
var
// Broj bajtova upisanih u fajl
WriteCount: Cardinal;
I: Integer;
Len: Integer;
begin
// Pretpostavimo da ce doci do greske
Result := -1;
// Upisemo header
BlockWrite(HFile, CROOM_HEADER, SizeOf(CROOM_HEADER), WriteCount);
if WriteCount <> SizeOf(CROOM_HEADER) then
Exit;
// Uzimamo broj soba iz niza ako korisnik nije nista uneo
if Count = 0 then
Count := High(Rooms) + 1;
// Upisujemo broj soba
BlockWrite(HFile, Count, SizeOf(Count), WriteCount);
if WriteCount <> SizeOf(Count) then
Exit;
// snimanje soba
for I := 0 to Count - 1 do
begin
// Upisujemo duzinu opisa
Len := Length(Rooms[I].Decription);
BlockWrite(HFile, Len, SizeOf(Len), WriteCount);
if WriteCount <> SizeOf(Len) then
Exit;
// Upisujemo opis sobe
BlockWrite(HFile, Rooms[I].Decription[1], Len, WriteCount);
if WriteCount <> Len then
Exit;
// Upisujemo prolaze do drugih soba
BlockWrite(HFile, Rooms[I].Doors, SizeOf(Rooms[I].Doors), WriteCount);
if WriteCount <> SizeOf(Rooms[I].Doors) then
Exit;
end;
// Sve je uspesno zavrseno
Result := Count;
end;
Na ovaj nacin je moguce snimiti podatke u bilo koji fajl (korisnik moze da prosleti funkciji otvoren handle fajla i podaci ce tu biti upisani). Posto se u fajl upisuje broj soba funkcija za citanje lako moze da odredi koliko iz fajla treba da procita. Na pocetku fajla se upisuje header (ovo nije uvek potrebno) da bi se lakse detektovao ostecen fajl.
Kada imamo ove funkcije, treba nam editor za sobe. Neki najjednostavniji editor bi trebalo da moze da snimi i ucita sobe sa diska, doda nove i promeni ili izbrise postojece.
Snimanje i ucitavanje smo vec sredili.
Kreiranje novih soba je prilicno lako. Dovoljno je da povecamo niz i ubacimo podatke za sobu. Ovakav nacin je definitivno spor jer prilikom prosirenja niza FPC mora da kreira nov niz i da u njega prekopira podatke iz onog koji smo vec napunili. Zbog toga se obicno zauzme malo vise prostora kad god se popuni niz, a treba jos da se doda. Npr: niz je prazan, a mi hocemo da dodamo jednu sobu. Program bi mogao da zauzme mesta dovoljno za 5 soba, a da popuni samo prvu. U nekoj internoj promenljivoj cuva da ima samo jednu popunjenu sobu. Dodavanje druge, trece, cetvrte i pete sobe se svodi samo na popunjavanje podataka i povecavanja interne promenljive za 1. Kada budemo hteli da ubacimo sestu sobu, program bi opet mogao da zauzme mesta za jos 5 i opet iz pocetka...
Menjanje sobe je lakse nego kreiranje. Sve sto treba je da zamenimo vrednosti novim i to je to.
Brisanje sobe je najkomplikovanije. Pre nego sto uopste obrisemo sobu, moramo u svim ostalim sobama da podesimo gde vrata vode. Ako neka vrata vode u sobu koju cemo da obrisemo, ta vrata ce voditi u nepostojecu sobu i moramo da postavimo da ta vrata vise nikuda ne vode. Posto cemo izbaciti jedan element iz niza, svi koji se nalaze iza njega ce se pomeriti na jednu poziciju nize i time ce indexi prostorija na koje vrata pokazuju biti pogresni pa i njih moramo smanjiti za 1 za sva vrata koja vode u sobe koje imaju index veci od sobe koju brisemo. Kada sve to zavrsimo, mozemo da obrisemo sobu. Prvo sve sobe koje se nalaze iza sobe za brisanje pomerimo za jedno mesto u nazad i na kraju smanjimo niz za jedno msto. Naravno, svako pomeranje elemenata i smanjivanje niza je prilicno sporo i zato te operacije treba sto manje koristiti. Postoje specijalni nizovi kod kojih je brisanje vrlo brzo (povezane liste), ali je pozicioniranje na neki slucajni element prilicno sporo, ili nizovi koji brzo mogu da dodaju ili brisu elemente samo na pocetku ili kraju niza... na programeru je da odluci kakav niz mu najvise odgovara za odredjeni problem.
Napisao sam jedan vrlo jednostavan editor koji radi u textualnom modu. Nema nikakvih optimizacija i kod je vrlo lak za razumevanje. Sledece sto nas ocekuje je pravljenje editora u grafuckom okruzenju (GUI). Od sada cemo da radimo sa Lazarusom i da koristimo njegov LCL za kreiranje programa.
Cekamo da neko napravi editor za sobe u grafickom okruzenju pa cemo da predjemo na pravljenje igre koja ce koristiti fajl sa sobama koji cemo kreirati u editoru.