program floodFill;
uses
crt,
Contnrs,
SysUtils;
const
MAXROWS = 19;
MAXCOLUMNS = 19;
BLOCKVALUE = 500;
type
PtrProg = ^smellCoordinates;
smellCoordinates = record
tileX, tileY: smallint;
distance: byte;
end;
var
r, c, counter: byte;
Queue: TQueue;
PtrShow: PtrProg;
myArray: array[1..MAXROWS, 1..MAXCOLUMNS] of string; // the map that is used as input
smellMap: array [1..MAXROWS, 1..MAXCOLUMNS] of smallint; // map that is output
(* Add a tile to the queue *)
procedure addTile(y, x, dist: byte);
var
PtrNew: PtrProg;
begin
new(PtrNew);
PtrNew^.tileX := x;
PtrNew^.tileY := y;
PtrNew^.distance := dist;
Queue.Push(PtrNew);
end;
procedure floodFillGrid(currentTile: PtrProg);
begin
while Queue.Count > 0 do
begin
// Increment distance counter
Inc(counter);
// check within bounds of grid
if (currentTile^.tileY >= 1) and (currentTile^.tileY <= MAXROWS) and
(currentTile^.tileX >= 1) and (currentTile^.tileX <= MAXCOLUMNS) then
begin
if (myArray[currentTile^.tileY][currentTile^.tileX] = '.') then
begin //select adjacent squares that aren't blocking walls
// give the selected square a distance value of the counter
if (myArray[currentTile^.tileY + 1][currentTile^.tileX] = '.') then
addTile(currentTile^.tileY + 1, currentTile^.tileX, counter);
if (myArray[currentTile^.tileY - 1][currentTile^.tileX] = '.') then
addTile(currentTile^.tileY - 1, currentTile^.tileX, counter);
if (myArray[currentTile^.tileY][currentTile^.tileX + 1] = '.') then
addTile(currentTile^.tileY, currentTile^.tileX + 1, counter);
if (myArray[currentTile^.tileY][currentTile^.tileX - 1] = '.') then
addTile(currentTile^.tileY, currentTile^.tileX - 1, counter);
// draw distance on the map
if (myArray[currentTile^.tileY][currentTile^.tileX] = '.') then
begin
(* drawn on the original map, just to make it easier to visualise while testing *)
myArray[currentTile^.tileY][currentTile^.tileX] :=
IntToStr(currentTile^.distance);
(* Draw the distance from the target onto the smell map *)
smellMap[currentTile^.tileY][currentTile^.tileX] := currentTile^.distance;
end;
end
else;
(* send the next tile to the floodfill procedure *)
PtrShow := Queue.Pop;
floodFillGrid(PtrShow);
end;
end;
end;
begin
// create queue
Queue := TQueue.Create;
Randomize;
// quick and dirty map
for r := 1 to MAXROWS do
begin
for c := 1 to MAXCOLUMNS do
begin
myArray[r][c] := '#';
end;
end;
for r := 2 to (MAXROWS - 1) do
begin
for c := 2 to (MAXCOLUMNS - 1) do
begin
if (random(3) <> 1) then
myArray[r][c] := '.';
end;
end;
myArray[2][2] := '.'; // starting tile is not a wall
// initialise smell map
for r := 1 to MAXROWS do
begin
for c := 1 to MAXCOLUMNS do
begin
if (myArray[r][c] = '#') then
smellMap[r][c] := BLOCKVALUE
else
smellMap[r][c] := 0;
end;
end;
// set distance counter to 1
counter := 1;
// add first tile to Queue twice (bit of a hack) so queue length is non-zero at start
addTile(2, 2, counter);
addTile(2, 2, counter);
// Send first tile to flood fill procedure
PtrShow := Queue.Pop;
floodFillGrid(PtrShow);
(* Draw the map *)
ClrScr;
for r := 1 to MAXROWS do
begin
for c := 1 to MAXCOLUMNS do
begin
// GotoXY(c, r);
Write(myArray[r][c], ' ');
end;
writeln;
end;
writeln;
readkey;
(* Draw the smell map *)
ClrScr;
for r := 1 to MAXROWS do
begin
for c := 1 to MAXCOLUMNS do
begin
// GotoXY(c, r);
Write(smellMap[r][c], ' ');
end;
writeln;
end;
writeln;
readkey;
end.