home *** CD-ROM | disk | FTP | other *** search
- program Maze;
- (*
- **
- *** Create and solve mazes on the "tube"
- *
- * Thanks to: "Advanced PASCAL Programming Techniques"
- * Paul A. Sand - Osborne/McGraw-Hill
- **
- *)
- CONST
- MAZECOLS = 79; (* Maximum Maze column index *)
- MAZEROWS = 22; (* Maximum Maze row index *0
- MAXCOLS = 79; (* Maximum CRT horizontal postion *)
- MAXROWS = 23; (* Maximum CRT vertical position *)
- XIndent:integer = 1; (* left margin amount *)
- YIndent:integer = 1; (* top margin amount *)
- SPEED:Integer = 0; (* speed of action *)
-
- TYPE
- mazesquare = (WALL,PATH);
- mazearray = array [0..MAZEROWS, 0..MAZECOLS] of mazesquare;
- direction = (UP, DOWN, LEFT, RIGHT);
-
- VAR
- Maze : mazearray;
- won : boolean;
- ch : char;
- mins,
- secs : integer;
-
- (*$I CreateMaze.pas *)
- (*
- **
- *** Create a maze in MAZEARRAY
- **
- *)
-
- Procedure DispSquare( CH:Char; row, col : Integer );
- (* Display specified character in maze square *)
- begin (* DispSquare *)
- gotoXY( col+XINDENT, row+YINDENT );
- write( ch );
- delay( SPEED )
- end;
-
- Procedure CREATEMAZE( Var Maze : mazearray );
-
- VAR
- row,
- col : integer;
- dir : direction;
-
- Procedure SetSquare( row, col : Integer; Val:Mazesquare );
- (* Set the maze square to a given value *)
- begin (* SetSquare *)
- maze[row, col] := val;
- case val of
- PATH : dispsquare(' ', row, col );
- WALL : dispsquare('X', row, col );
- end
- end;
-
- Function rnd( low, high : Integer ):Integer;
- (* Return random value with limits *)
-
- begin (* rnd *)
- rnd := low + random(high-low+1)
- end (* rnd *);
-
- Function rnddir : Direction;
- (* returns a random, legal direction *)
- begin (* rnddir *)
- case rnd(1,4) of
- 1: rnddir := UP;
- 2: rnddir := DOWN;
- 3: rnddir := LEFT;
- 4: rnddir := RIGHT
- end
- end (* rnddir *);
-
- Function LegalPath( row, col: Integer; dir: Direction): boolean;
- (* returns legality of path *)
- VAR
- Legal : Boolean;
-
- BEGIN (* legal Path *)
- legal := FALSE;
- case dir of
- UP : if row > 2
- then legal := ( maze[row-2,col] = WALL);
- LEFT : if col > 2
- then legal := ( maze[row,col-2] = WALL);
- DOWN : if row < MAZEROWS - 2
- then legal := ( maze[row+2,col] = WALL);
- RIGHT: if col < MAZECOLS - 2
- then legal := ( maze[row,col+2] = WALL);
- end;
- LegalPath := legal
- end (* LegalPath *);
-
- Procedure BuildPath( row,col : Integer; Dir : direction );
- (* extend a path in specified direction *)
- VAR
- Unused : set of direction;
-
- Begin(* BuildPath *)
- case dir of
- UP: begin
- setsquare(row-1,col,path );
- setsquare(row-2,col,path );
- row := row-2
- end;
- DOWN: begin
- setsquare(row+1,col,path );
- setsquare(row+2,col,path );
- row := row+2
- end;
- LEFT: begin
- setsquare(row,col-1,PATH);
- setsquare(row,col-2,PATH);
- col := col-2
- end;
- RIGHT: begin
- setsquare(row,col+1,PATH);
- setsquare(row,col+2,PATH);
- col := col+2
- end
- end;
- unused := [UP..RIGHT];
- repeat
- dir := rnddir;
- if dir in unused
- then begin
- unused := unused - [dir];
- if LegalPath(row,col,dir)
- then buildpath(row,col,dir)
- end;
- until unused = []
- end;
-
- begin (* Createmaze *)
- for row := 0 to MAZEROWS do
- for col := 0 to MAZECOLS do
- setsquare( row, col, WALL );
- row := 2 * rnd(0,MAZEROWS div 2 - 1) + 1;
- col := 2 * rnd(0,MAZECOLS div 2 - 1) + 1;
- setsquare( row,col,PATH );
- repeat
- dir := rnddir
- until legalpath( row,col,dir );
- buildpath( row,col,dir );
- col := 2 * rnd(0,MAZECOLS div 2 - 1) + 1;
- setsquare( 0,col,PATH );
- col := 2 * rnd(0,MAZECOLS div 2 - 1) + 1;
- setsquare( MAZEROWS,col,PATH )
- end (* CreateMaze *);
- (*$I SolveMaze.pas *)
- (*
- **
- *** Solve the Maze
- **
- *)
-
- Procedure ShowMove( row,col : Integer; dir : direction );
- (* show a move *)
- begin
- case dir of
- UP, DOWN: dispsquare('!',row,col);
- RIGHT, LEFT: dispsquare('-',row,col)
- end
- end;
-
- Procedure EraseMove(row,col:Integer);
- (* Erase a move *)
- VAR
- SaveSpeed : integer;
- begin (* EraseMove *)
- SaveSpeed := Speed; Speed := 0;(* rewind at full speed *)
- dispsquare(' ',row,col); speed := SaveSpeed;
- end;
-
-
- Function SolveMaze( VAR maze : mazearray ) : Boolean;
- (* attempt to solve the maze *)
- VAR
- solved : boolean;
- row, col : Integer;
- tried : array [0..MAZEROWS, 0..MAZECOLS] of Boolean;
-
- Function Try(row, col : Integer; dir : direction ): boolean;
- (* test solution from this point *)
- VAR
- ok : boolean;
-
- begin (* try *)
- ok := (maze[row,col] = PATH);
- if ok then begin
- tried[row,col] := TRUE;
- case dir of
- UP: row := pred(row);
- DOWN: row := succ(row);
- LEFT: col := pred(col);
- RIGHT: col := succ(col)
- end;
- ok := ((maze[row,col]=PATH) and (not tried[row,col]));
- if ok then begin
- showmove(row,col,dir);
- ok := (row <= 0) or (row >= MAZEROWS) or
- (col <= 0) or (col >= MAZECOLS);
- if NOT ok
- then ok := try(row,col,DOWN);
- if NOT ok
- then ok := try(row,col,LEFT);
- if NOT ok
- then ok := try(row,col,RIGHT);
- if NOT ok
- then ok := try(row,col,UP);
- if NOT ok
- then (* no solution available from this point *) erasemove(row,col)
- end;
- end;
- try := ok;
- end;
-
- begin(* solvemaze *)
- for row := 0 to MAZEROWS do
- for col := 0 to MAZECOLS do
- tried [row,col] := FALSE;
- solved := false;
- col := 0; row := 1;
- while NOT solved and (row < MAZEROWS) do begin
- solved := try(row,col,RIGHT);
- row := succ(row)
- end;
- col := MAZECOLS; row := 1;
- while NOT solved and (row < MAZEROWS) do begin
- solved := try(row,col,LEFT);
- row := succ(row)
- end;
- col := 1; row := 0;
- while NOT solved and (row < MAZEROWS) do begin
- solved := try(row,col,DOWN);
- col := succ(col)
- end;
- col := 1; row := MAZEROWS;
- while NOT solved and (row < MAZEROWS) do begin
- solved := try(row,col,UP);
- col := succ(col)
- end;
- solvemaze := solved
- end (* SolveMaze *);
-
- Begin (* Maze *)
- randomize;
- (* Note: a timer routine has not been implemented yet *)
- repeat
- ClrScr;
- createmaze( maze );
- gotoXY( 10,MAXROWS+1 );
- write( 'Press <C> to Continue' ); read( ch );
- speed := 100;(* slow it down so we can watch *)
- LowVideo;(* change the appearance of the "snake" *)
- (* start := timer; *)
- won := solvemaze( maze );
- (* finish := timer *)
- (* mins := finish-start mod 60; *)
- (* secs := finish-start div 60; *)
- NormVideo;(* go back to standard intensity *)
- gotoXY( 1,MAXROWS+1 );write( 'Time to solve: xx Mins and xx Seconds' );
- gotoXY( WHereX-22,WhereY );Write( mins:2 );
- gotoXY( WhereX+10,WhereY );Write( secs:2 );
- gotoXY( 40,WhereY );write( 'Press <C> to Continue, <Q> to Quit ' );
- speed := 0;(* reset for re-build *) read( ch )
- until UpCase(ch) = 'Q';
- ClrScr
- end (* Maze *).