home *** CD-ROM | disk | FTP | other *** search
- PROGRAM Maze;
- {adapted from "Advanced Pascal Programming Techniques"
- by Paul A. Sand
- }
-
- CONST
- MAZECOLS = 79;
- MazeRows = 22;
- MaxCRTCol = 80;
- MaxCRTRow = 25;
- (* ===== MONO attributes A ==== *)
- (* NewPath = LightGray; { Maze is "LowVideo" color. Path out }
- BadPath = black; { is "HighVideo". Reject paths are }
- OutPath = white; { simply erased from the screen. }
- BakGrnd = black;*)
- (* ===== MONO attributes B ==== *)
- (* NewPath = White; { Maze is "HighVideo" color. Path out }
- BadPath = lightGray; { is reverse video -- kind of ugly. }
- OutPath = black; { Rejected paths are set to "LowVideo".}
- BakGrnd = lightGray;*)
- (* ===== COLOR attributes ==== *)
- NewPath = LightCyan; { In color, it works fine.}
- OutPath = LightBlue;
- BadPath = Cyan;
- BakGrnd = white;
- TYPE
- direction = (Up, Down, Left, Right, Out);
- dirset = set of direction;
- MazeArray = ARRAY[0..MazeRows, 0..MazeCols] OF DirSet;
-
- VAR
- Maze : mazeArray;
- Got_Out : Boolean;
- CH : Char;
-
-
- function num_of(VAR D): byte;
- { This function takes advantage of the fact that the elements
- of a set are represented by setting BITS within the SET
- variable. If the first item is present in the set, the
- first bit will be a 1. }
- var
- X : byte absolute D;
- begin
- num_of := X;
- end;
-
-
- PROCEDURE Mark_Square(CH : Char; row, col : Integer);
- BEGIN
- GoToXY(col+1, row+1);
- Write(CH);
- END; { procedure Mark_Square(CH : char; row,col : integer) }
-
- PROCEDURE SetSquare(row, col : Integer; wp : DirSet);
- BEGIN
- maze[row, col] := wp;
- if out in WP then
- TextColor(Yellow + Blink);
- CASE (Num_Of(wp) and $F) OF
- 0: Mark_Square(' ', row, col);
- 1: IF col = 0 THEN
- Mark_Square('S', row, col)
- ELSE
- Mark_Square('=', row, col);
- 2: IF col = 0 THEN
- Mark_Square('V', row, col)
- ELSE
- Mark_Square('7', row, col);
- 3: Mark_Square(':', row, col);
- 4: IF row = 0 THEN
- Mark_Square('8', row, col)
- ELSE
- Mark_Square('>', row, col);
- 5: Mark_Square('<', row, col);
- 6: Mark_Square(';', row, col);
- 7: Mark_Square('9', row, col);
- 8: IF row = 0 THEN
- Mark_Square('U', row, col)
- ELSE
- Mark_Square('T', row, col);
- 9: Mark_Square('H', row, col);
- 10: Mark_Square('I', row, col);
- 11: Mark_Square('L', row, col);
- 12: Mark_Square('M', row, col);
- 13: Mark_Square('J', row, col);
- 14: Mark_Square('K', row, col);
- 15: Mark_Square('N', row, col);
- END;
- TextColor(NewPath);
- END; { procedure SetSquare() }
-
-
-
- PROCEDURE CreateMaze(VAR Maze : MazeArray);
- {CREATED: 11/24/1985}
- VAR
- row, col : Integer;
- dir : direction;
-
- FUNCTION randdir : direction;
- BEGIN
- CASE Random(4) OF
- 0 : randdir := Up;
- 1 : randdir := Down;
- 2 : randdir := Left;
- 3 : randdir := Right;
- END;
- END; { function randdir }
-
- FUNCTION legalPath(row, col : Integer; dir : direction) : Boolean;
- (* ============================================================ *)
- (* It's legal to extend the path in a given direction IFF that *)
- (* extension would NOT intersect an already-created path. *)
- (* ============================================================ *)
- VAR
- legal : Boolean;
- BEGIN
- legal := False;
- CASE dir OF
- Up : IF row > 0 THEN
- Legal := (maze[row-1, col] = []);
- Down : IF row < MazeRows THEN
- Legal := (maze[row+1, col] = []);
- Left : IF col > 0 THEN
- Legal := (maze[row, col-1] = []);
- Right : IF col < MazeCols THEN
- Legal := (maze[row, col+1] = []);
- END;
- legalPath := legal;
- END; { function legalPath(row,col : integer; dir : direction) }
-
-
- PROCEDURE BuildPath(row, col : Integer; dir : direction);
- (* ============================================================ *)
- (* BuildPath is first called with a starting location and a *)
- (* direction. If it's legal to go in that direction, it does *)
- (* so. Then it attempts to BuildPath from the new location *)
- (* in each of the four directions. Highly recursive! *)
- (* ============================================================ *)
- VAR
- unused : dirset;
- BEGIN
- CASE dir OF
- Up : BEGIN
- SetSquare(row, col, Maze[row,col] + [up]);
- SetSquare(row-1, col, Maze[row-1,col] + [down]);
- row := row-1;
- END;
- Down : BEGIN
- SetSquare(row, col, Maze[row,col] + [down]);
- SetSquare(row+1, col, Maze[row+1,col] + [up]);
- row := row+1;
- END;
- Left : BEGIN
- SetSquare(row, col, Maze[row,col] + [left] );
- SetSquare(row, col-1, Maze[row,col-1] + [right]);
- col := col-1;
- END;
- Right : BEGIN
- SetSquare(row, col, Maze[row,col] + [right]);
- SetSquare(row, col+1, Maze[row,col+1] + [left]);
- col := col+1;
- END;
- END;
- Unused := [Up..Right];
-
- REPEAT
- dir := randdir;
- IF Dir IN unused THEN
- BEGIN
- unused := unused-[dir];
- IF LegalPath(row, col, dir) THEN
- BuildPath(row, col, dir); {<< note the recursive call!}
- END;
- UNTIL unused = [];
- END; { procedure BuildPath(row,col : integer; dir : direction) }
-
-
- BEGIN
- FillChar(Maze, SizeOf(Maze),0);
- col := random(MazeCols);
- row := random(MazeRows);
- REPEAT
- dir := randdir
- UNTIL LegalPath(row, col, dir);
- buildPath(row, col, dir);
- {Now make an exit -- or don't!}
- case random(17) of
- 0..3: begin {UP exit}
- col := Random(MazeCols);
- SetSquare(0, col, Maze[0,col] + [out,up]);
- end;
- 4..7: begin {DOWN exit}
- col := random(MazeCols);
- SetSquare(MazeRows,col, Maze[MazeRows,col] + [out,down]);
- end;
- 8..11: begin {LEFT exit}
- row := random(MazeRows);
- SetSquare(row,0, Maze[row,0] + [out,left]);
- end;
- 12..15: begin {RIGHT exit}
- row := random(MazeRows);
- SetSquare(row,MazeCols, Maze[row,MazeCols] + [out,right]);
- end;
- 16:; {no exit}
- end;
- END; { procedure CreateMaze(VAR Maze : MazeArray) }
-
- FUNCTION SolveMaze(VAR Maze : MazeArray) : Boolean;
- VAR
- Solved : Boolean;
- row, col : Integer;
- tried : ARRAY[0..MazeRows, 0..mazeCols] OF Boolean;
-
- FUNCTION try(row, col : Integer; dir : direction) : Boolean;
- VAR ok : Boolean;
-
- PROCEDURE Mark_Forward(row, col : Integer);
- BEGIN
- TextColor(OutPath);
- SetSquare(row,col,Maze[row,col]);
- END; { procedure Mark_Forward(row,col : integer; dir : direction) }
-
- PROCEDURE Mark_Backward(row, col : Integer);
- BEGIN
- TextColor(BadPath);
- SetSquare(row,col,Maze[row,col]);
- END; { procedure Mark_Backward(row,col : integer); }
-
- BEGIN
- (* delay(20);*)
- ok := (dir in maze[row, col]);
- IF OK THEN
- BEGIN
- tried[row, col] := True;
- CASE dir OF
- Up : row := row-1;
- Down : row := row+1;
- Left : col := col-1;
- Right : col := col+1;
- END;
- OK := (NOT tried[row, col]);
- IF OK THEN
- BEGIN
- Mark_Forward(row, col);
- OK := out in maze[row,col];
- IF NOT OK THEN
- OK := try(row, col, Left);
- IF NOT OK THEN
- OK := try(row, col, down);
- IF NOT OK THEN
- OK := try(row, col, right);
- IF NOT OK THEN
- OK := try(row, col, up);
- IF NOT OK THEN
- Mark_Backward(row, col);
- END;
- END;
- try := ok;
- END; { function try(row,col:integer; dir : direction) }
-
-
- BEGIN
- FOR row := 0 TO MazeRows DO
- FOR col := 0 TO MazeCols DO
- tried[row, col] := False;
- col := 2*(Random((MazeCols DIV 2)-1))+1;
- row := 2*(Random((MazeRows DIV 2)-1))+1;
- TextColor(Yellow + Blink);
- SetSquare(row,col,Maze[row,col]);
- TextColor(NewPath);
- GoToXY(1, MaxCRTRow);
- Write('Press a key to find the way out from the blinking yellow spot');
- REPEAT UNTIL KeyPressed; Read(Kbd);
- TextColor(OutPath);
- solved := out in Maze[row,col];
- if not solved then
- solved := try(row, col, RIGHT);
- if not solved then
- solved := try(row,col,left);
- if not solved then
- solved := try(row,col,up);
- if not solved then
- solved := try(row,col,down);
- SolveMaze := solved;
- END; { function SolveMaze(VAR Maze:MazeArray) }
-
-
- BEGIN
- Randomize;
- REPEAT
- TextBackground(bakGrnd);
- TextColor(NewPath);
- ClrScr;
- CreateMaze(Maze);
- Got_Out := SolveMaze(Maze);
- GoToXY(1, MaxCRTRow); ClrEOL;
- IF Got_Out THEN Write('SUCCEEDED! ')
- ELSE Write('FAILED . . .');
- Write('<C> to continue, <Q> to quit');
- REPEAT UNTIL KeyPressed;
- Read(Kbd, CH);
- UNTIL UpCase(CH) = 'Q';
- ClrScr;
- END.
-