This is a simple maze solver program. It it based on mazes from the Micromouse competition. As the mouse does not know the maze beforehand it has to find its way by trial and error. It marks all junctions with an X and puts each one it passes on a stack. When it goes into a dead end the last few junctions are deleted from the stack and it tries another direction from the junction where it entered the deadend. This gives a reasonably fast route but I don't think it is optimal as there may be several routes from start to finish and the one it finds first may not be the fastest. Also it can get surplus loops in its final route which are easy to remove but I didn't implement this as it would have meant more work and testing.
I expanded this program in stages. I started by just drawing the maze on the screen, then got it so the user could move the mouse around using direction keys. Pascal has a turtle graphics thing which was designed to control robots with pens, so I used this. You just set the angle and forward distance. Then I got the mouse to go from junction to junction picking the next path at random. It never once managed to reach the centre of the maze with this method. What actually happened was it sort of got a way then kept getting 'dragged' back to the start like the force of gravity, actually it was the force of probabilities evening out. As you can imagine, say 20 junctions with 2 or 3 routes = 2 to the power 20. Less than a 1 in a million chance. So I then got it to cancel routes it had tried out and it worked, then added a routine to optimise the route.
Programmed using Borland Pascal with Libraries. Download FREE from the Internet. You might also want Object Orientated Pascal for more complicated Programmes. The mouse can always find it's way to the centre of the Maze, by searching and blocking dead-ends. With Random selection it never gets more than half way to the centre due to a 'Probability Well'. Also it has to know that's where it wants to go in the first place.
program mouse; uses graph3, crt, maze; type JUNCTION_RECORD = RECORD x: INTEGER; y: INTEGER; back: INTEGER; end; { Record } var name: STRING; any_maze, new_maze: MAZE_ARRAY; choice, key: CHAR; loop, loop2, x_pos, y_pos, x_wall, y_wall, stack, direction, null: INTEGER; is_junction: ARRAY [1..16,1..16] OF BOOLEAN; junction: ARRAY [0..100] OF JUNCTION_RECORD; path: ARRAY [1..50] OF INTEGER; procedure move (turtle_direction: INTEGER); begin setheading(turtle_direction*90); forwd (10); case turtle_direction of 0: y_pos := y_pos - 1; 1: x_pos := x_pos + 1; 2: y_pos := y_pos + 1; 3: x_pos := x_pos - 1; end; { Case } x_wall := x_pos * 2; y_wall := y_pos * 2; end; {move} procedure move_and_log (turtle_direction: INTEGER); begin move (turtle_direction); if is_junction [x_pos,y_pos] then begin junction[stack].x := x_pos; junction[stack].y := y_pos; junction[stack].back := (turtle_direction+2) MOD 4; stack:=stack+1; end; end; {move_and_log} procedure goto_next_junction (junction_heading: INTEGER); var opersite, heading: INTEGER; begin if is_junction [x_pos,y_pos] AND NOT ((junction[stack-1].x = x_pos) AND (junction[stack-1].y = y_pos)) then begin opersite := (junction_heading+2) MOD 4; move_and_log (junction_heading); end; while NOT is_junction [x_pos,y_pos] do begin if (new_maze [y_wall-1][x_wall ] <> '-') AND (opersite <> 0) then heading:=0; if (new_maze [y_wall ][x_wall+1] <> 'Ý') AND (opersite <> 1) then heading:=1; if (new_maze [y_wall+1][x_wall ] <> '-') AND (opersite <> 2) then heading:=2; if (new_maze [y_wall ][x_wall-1] <> 'Ý') AND (opersite <> 3) then heading:=3; opersite := (heading+2) MOD 4; move_and_log (heading); end; end; { goto_next_junction } function goto_and_log (junction_heading: INTEGER):INTEGER; var opersite, heading: INTEGER; begin heading:=junction_heading; opersite := (heading+2) MOD 4; move (heading); while NOT is_junction [x_pos,y_pos] do begin if (new_maze [y_wall-1][x_wall ] <> '-') AND (opersite <> 0) then heading:=0; if (new_maze [y_wall ][x_wall+1] <> 'Ý') AND (opersite <> 1) then heading:=1; if (new_maze [y_wall+1][x_wall ] <> '-') AND (opersite <> 2) then heading:=2; if (new_maze [y_wall ][x_wall-1] <> 'Ý') AND (opersite <> 3) then heading:=3; opersite := (heading+2) MOD 4; move (heading); end; goto_and_log:=(heading+2) MOD 4; end; {goto_and_log} procedure go_back; var exit: INTEGER; begin if (wall_count (x_pos, y_pos, new_maze) = 3) then begin if (new_maze [y_wall-1][x_wall ] <> '-') then exit:=0; if (new_maze [y_wall ][x_wall+1] <> 'Ý') then exit:=1; if (new_maze [y_wall+1][x_wall ] <> '-') then exit:=2; if (new_maze [y_wall ][x_wall-1] <> 'Ý') then exit:=3; goto_next_junction (exit); stack:=stack-1; end else if is_junction[x_pos,y_pos] then begin stack:=stack-1; goto_next_junction (junction[stack].back); end; end; {go_back} procedure block_and_move (turtle_direction: INTEGER); begin case turtle_direction of 0: new_maze [y_wall-1][x_wall ] := 'B'; 1: new_maze [y_wall ][x_wall+1] := 'B'; 2: new_maze [y_wall+1][x_wall ] := 'B'; 3: new_maze [y_wall ][x_wall-1] := 'B'; end; move_and_log (turtle_direction); end; {block_and_move} begin {main} repeat clrscr; writeln ('(C)hicago'); writeln ('(J)apan'); writeln ('(L)ondon'); writeln ('(Q)uit'); repeat choice:=readkey; choice:=upcase(choice); if choice = 'C' then init_chicago_maze (name, any_maze); if choice = 'J' then init_japan_maze (name, any_maze); if choice = 'L' then init_london_maze (name, any_maze); until (choice='C') OR (choice='J') OR (choice='L') OR (choice='Q'); if choice <> 'Q' then begin for loop:=1 to 50 do path[loop]:=0; for loop:=0 to 100 do begin junction[loop].x:=0; junction[loop].y:=0; junction[loop].back:=0; end; stack:=1; new_maze := any_maze; new_maze[33][2]:='-'; { Block start } write_text (name); draw_maze (new_maze, GREEN); for x_pos := 1 to 16 do for y_pos := 1 to 16 do if wall_count (x_pos, y_pos, new_maze) < 2 then begin draw ((x_pos*10)+12,(y_pos*10)+14,(x_pos*10)+20,(y_pos*10)+22,RED); draw ((x_pos*10)+20,(y_pos*10)+14,(x_pos*10)+12,(y_pos*10)+22,RED); is_junction [x_pos,y_pos] := TRUE; end else is_junction [x_pos,y_pos] := FALSE; penup; setposition (-133, -80); pendown; showturtle; x_pos := 1; y_pos := 16; x_wall := x_pos * 2; y_wall := y_pos * 2; for loop := 1 to 20000 do begin randomize; direction := random(4); delay (10); if (roadblock_count (x_pos, y_pos, new_maze) = 3) AND is_junction [x_pos,y_pos] then begin if (new_maze [y_wall-1][x_wall ] = ' ') then direction:=0; if (new_maze [y_wall ][x_wall+1] = ' ') then direction:=1; if (new_maze [y_wall+1][x_wall ] = ' ') then direction:=2; if (new_maze [y_wall ][x_wall-1] = ' ') then direction:=3; block_and_move (direction); end else begin if (direction = 0) AND (new_maze [y_wall-1][x_wall] = ' ') then block_and_move (0); if (direction = 1) AND (new_maze [y_wall][x_wall+1] = ' ') then block_and_move (1); if (direction = 2) AND (new_maze [y_wall+1][x_wall] = ' ') then block_and_move (2); if (direction = 3) AND (new_maze [y_wall][x_wall-1] = ' ') then block_and_move (3); end; { Check if centre reached } if ((x_pos = 8) AND (y_pos = 8)) OR ((x_pos = 8) AND (y_pos = 9)) OR ((x_pos = 9) AND (y_pos = 8)) OR ((x_pos = 9) AND (y_pos = 9)) then begin key := readkey; loop:=20000; end else if (roadblock_count (x_pos, y_pos, new_maze) = 4) then go_back; end; penup; setheading(270); forwd(63); pendown; x_pos:=junction[stack-1].x; y_pos:=junction[stack-1].y; x_wall:=x_pos*2; y_wall:=y_pos*2; loop2:=1; stack:=stack-1; for loop:=stack downto 2 do begin if NOT ((junction[loop].y = junction[loop-1].y) AND (junction[loop].x = junction[loop-1].x)) then begin path[loop2]:=goto_and_log(junction[loop].back); loop2:=loop2+1; end; end; write_text (name); draw_maze (new_maze, GREEN); penup; setheading(270); forwd(133); setheading(180); forwd(80); pendown; x_pos := 1; y_pos := 16; x_wall:=x_pos*2; y_wall:=y_pos*2; for loop:=loop2 downto 1 do null:=goto_and_log(path[loop]); key:=readkey; end; {if} until choice = 'Q'; clrscr; textmode(BW80); end. { mouse }