1+ # MAZE TRAVERSAL
2+
3+ import curses
4+ from curses import wrapper
5+ import queue
6+ import time
7+ import sys
8+
9+ # maze = [
10+ # ["#", "O", "#", "#", "#", "#", "#", "#", "#"],
11+ # ["#", " ", " ", " ", " ", " ", " ", " ", "#"],
12+ # ["#", " ", "#", "#", " ", "#", "#", " ", "#"],
13+ # ["#", " ", "#", " ", " ", " ", "#", " ", "#"],
14+ # ["#", " ", "#", " ", "#", " ", "#", " ", "#"],
15+ # ["#", " ", "#", " ", "#", " ", "#", " ", "#"],
16+ # ["#", " ", "#", " ", "#", " ", "#", "#", "#"],
17+ # ["#", " ", " ", " ", " ", " ", " ", " ", "#"],
18+ # ["#", "#", "#", "#", "#", "#", "#", "X", "#"]
19+ # ]
20+
21+ maze = [
22+ ["#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" ],
23+ ["#" , "O" , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , "#" ],
24+ ["#" , "#" , "#" , "#" , "#" , " " , "#" , "#" , "#" , "#" , "#" , "#" , "#" , " " , "#" , "#" , "#" , "#" , " " , "#" ],
25+ ["#" , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , "#" ],
26+ ["#" , " " , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , " " , "#" ],
27+ ["#" , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , "#" ],
28+ ["#" , " " , "#" , "#" , "#" , "#" , "#" , " " , "#" , "#" , "#" , "#" , "#" , " " , "#" , "#" , "#" , "#" , "#" , "#" ],
29+ ["#" , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , "#" ],
30+ ["#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , " " , "#" , "#" , "#" , "#" , "#" , "#" , "#" , " " , "#" ],
31+ ["#" , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , "#" ],
32+ ["#" , " " , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , " " , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" ],
33+ ["#" , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , "#" ],
34+ ["#" , " " , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , " " , "#" ],
35+ ["#" , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , "#" ],
36+ ["#" , "#" , "#" , "#" , "#" , "#" , "#" , " " , "#" , "#" , "#" , "#" , "#" , " " , "#" , "#" , "#" , "#" , "#" , "#" ],
37+ ["#" , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , "#" ],
38+ ["#" , " " , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , " " , "#" ],
39+ ["#" , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , "#" ],
40+ ["#" , " " , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "X" , "#" ],
41+ ["#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" , "#" ]
42+ ]
43+
44+ def print_maze (maze , stdscr , visited , path = []):
45+ blue = curses .color_pair (1 )
46+ red = curses .color_pair (2 )
47+ green = curses .color_pair (3 )
48+
49+ for row , i in enumerate (maze ):
50+ for column , j in enumerate (i ):
51+ if (row , column ) in path :
52+ stdscr .addstr (row , column * 2 , "X" , green )
53+ elif (row , column ) in visited :
54+ stdscr .addstr (row , column * 2 , "X" , red )
55+ else :
56+ stdscr .addstr (row , column * 2 , j , blue )
57+
58+
59+ def find (maze , start ): #to check and return starting position in maze
60+ for row , i in enumerate (maze ):
61+ for column , j in enumerate (i ):
62+ if j == start :
63+ return (row ,column ) # return tuple of row, column location of element in the maze
64+ return None
65+
66+ def find_neighbours (maze , row , col ): #search and return each neighbour of a particular cell, without checking if its a wall or not
67+ neighbours = []
68+
69+ if row > 0 : # for UP
70+ neighbours .append ((row - 1 , col ))
71+ if row + 1 < len (maze ): # for DOWN
72+ neighbours .append ((row + 1 , col ))
73+ if col + 1 < len (maze [0 ]): # for RIGHT
74+ neighbours .append ((row , col + 1 ))
75+ if col > 0 : # for LEFT
76+ neighbours .append ((row , col - 1 ))
77+ return neighbours
78+
79+
80+ def traverse (maze , stdscr ): #implementing bfs traversal
81+ start = "O"
82+ target = "X"
83+ start_pos = find (maze , start )
84+
85+ if start_pos == None :
86+ sys .exit ("Starting position not found!" )
87+
88+ q = queue .Queue () #initialise queue
89+ q .put ((start_pos , [start_pos ])) #put each position as well as path as a tuple
90+
91+ visited = set ()
92+
93+ while not q .empty ():
94+ current_pos , path = q .get ()
95+ row , col = current_pos
96+
97+ stdscr .clear ()
98+ print_maze (maze , stdscr , visited , path )
99+ # time.sleep(0.1)
100+ stdscr .refresh ()
101+
102+ if maze [row ][col ] == target :
103+ return path
104+
105+ neighbours = find_neighbours (maze , row , col )
106+ for nbr in neighbours :
107+ if nbr in visited :
108+ continue
109+
110+ r , c = nbr
111+ if maze [r ][c ] == "#" :
112+ continue
113+
114+ new_path = path + [nbr ]
115+ q .put ((nbr , new_path ))
116+ visited .add (nbr )
117+
118+
119+ def main (stdscr ):
120+ curses .init_pair (1 , curses .COLOR_BLUE , curses .COLOR_BLACK )
121+ curses .init_pair (2 , curses .COLOR_RED , curses .COLOR_BLACK )
122+ curses .init_pair (3 , curses .COLOR_GREEN , curses .COLOR_BLACK )
123+
124+ traverse (maze , stdscr )
125+
126+ stdscr .getch ()
127+
128+ # wrapper(main)
129+
130+
131+ if __name__ == '__main__' :
132+ wrapper (main )
0 commit comments