Skip to content

Commit f7b5dda

Browse files
authored
project files added
1 parent ed67d7f commit f7b5dda

File tree

4 files changed

+672
-0
lines changed

4 files changed

+672
-0
lines changed

algo.py

+92
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
import my_maze
2+
import math
3+
4+
def fill_shortest_path(board, start, end, max_distance=math.inf):
5+
"""
6+
7+
Finds and marks the shortest path in a maze from a start point to an end point.
8+
9+
Parameters:
10+
----------
11+
board (my_maze.Board):
12+
The board represents the maze structure, where each cell can be empty or a wall.
13+
14+
start (tuple):
15+
A tuple of two integers representing the starting position (row, column) in the maze.
16+
17+
end (tuple):
18+
A tuple of two integers representing the ending position (row, column) in the maze.
19+
20+
max_dist (int, optional):
21+
The maximum distance allowed for the path. If the shortest path exceeds this distance,
22+
the search is aborted. By default, it is set to `math.inf`, allowing for the maximum
23+
possible distance.
24+
25+
Returns:
26+
-------
27+
my_maze.Board
28+
A clone of the original `board` object with the shortest path marked.
29+
30+
"""
31+
nboard = board.clone()
32+
nboard.clear_count(math.inf) #infinite possibilities at start
33+
34+
nboard.at( start ).mark = my_maze.CellMark.Start
35+
nboard.at( end ).mark = my_maze.CellMark.End
36+
37+
open_list = [ start ]
38+
nboard.at( start ).count = 0
39+
neighbours = [[-1, 0], [1, 0], [0, 1], [0, -1]]
40+
41+
while open_list:
42+
current_pos = open_list.pop(0)
43+
current_cell = nboard.at( current_pos )
44+
for neighbour in neighbours:
45+
ncell_pos = my_maze.add_point(current_pos, neighbour)
46+
if not nboard.is_valid_point(ncell_pos):
47+
continue
48+
cell = nboard.at( ncell_pos )
49+
50+
if cell.type != my_maze.CellType.Empty:
51+
continue
52+
53+
dist = current_cell.count+1
54+
if dist > max_distance:
55+
continue
56+
57+
if cell.count > dist: #math.inf > 1
58+
cell.count = dist # cell.count = 1
59+
cell.path_from = current_cell # Records which cell we came from to reach this neighbor
60+
open_list.append(ncell_pos) #now we will search this This backtracking information
61+
#is used to reconstruct the path once the end cell is reached.
62+
return nboard
63+
64+
def backtrack_to_start(board, end):
65+
"""
66+
67+
Parameters:
68+
-----------
69+
board (my_maze.Board):
70+
The maze board object. The board represents the maze structure, where
71+
each cell can be empty or a wall.
72+
73+
end (tuple):
74+
A tuple of two integers representing the ending position (row, column) in the maze.
75+
76+
Returns:
77+
--------
78+
list:
79+
A list of `Cell` objects representing the path from the end position to the start
80+
position.
81+
82+
"""
83+
84+
cell = board.at( end )
85+
path = []
86+
while cell != None:
87+
path.append(cell)
88+
cell = cell.path_from
89+
90+
return path
91+
92+

draw_s_path.py

+299
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,299 @@
1+
import pygame, math
2+
import my_maze
3+
4+
pygame.init()
5+
pygame.display.set_caption("Demo => Path Finding")
6+
cell_font = pygame.font.SysFont(pygame.font.get_default_font(), 25)
7+
8+
def trans_rect(r, offset):
9+
"""
10+
11+
This function takes rect( => x,y,w,h <= ) then adjusts the position of rectangle by applying an offset to it
12+
13+
Parameters:
14+
-----------
15+
r (list): This parameter represents rectangle.
16+
17+
offset (list): This parameter represents the offset by which you want to move the rectangle.
18+
19+
Returns:
20+
--------
21+
(list):
22+
- The new x-coordinate of the rectangle's top-left corner.
23+
- The new y-coordinate of the rectangle's top-left corner.
24+
- The original width of the rectangle.
25+
- The original height of the rectangle
26+
27+
"""
28+
return [r[0]+offset[0], r[1]+offset[1], r[2], r[3]]
29+
30+
def main_loop(ui):
31+
"""
32+
33+
Run the main event loop of the application.
34+
35+
This function initializes the display, handles user input events, and updates the display based on the user interface (UI) object's draw method. The loop runs indefinitely until the user quits the application or presses the escape key.
36+
37+
Parameters
38+
----------
39+
ui : object
40+
An instance of a user interface class that has `step`, `reset`, and `draw` methods.
41+
42+
Returns
43+
-------
44+
None
45+
46+
"""
47+
48+
screen = pygame.display.set_mode((1000,800))
49+
50+
clock = pygame.time.Clock()
51+
clock.tick()
52+
while True:
53+
event = pygame.event.poll()
54+
if event.type == pygame.QUIT:
55+
break
56+
elif event.type == pygame.KEYDOWN:
57+
if event.key == pygame.K_ESCAPE:
58+
break
59+
if event.key == pygame.K_LEFT:
60+
ui.step(-1)
61+
if event.key == pygame.K_RIGHT:
62+
ui.step(1)
63+
if event.key == pygame.K_r:
64+
ui.reset()
65+
66+
ui.draw(screen)
67+
68+
pygame.display.update()
69+
clock.tick(60)
70+
71+
pygame.quit()
72+
73+
74+
class Finder:
75+
def __init__(self):
76+
self.board = None
77+
self.path = None
78+
79+
def set_board(self, board):
80+
"""
81+
82+
Set the board attribute of the instance.
83+
84+
Parameters
85+
----------
86+
self : object
87+
The instance of the class from which this method is called.
88+
89+
board : Board
90+
The board object to be set for the instance.
91+
92+
Returns
93+
-------
94+
None
95+
96+
"""
97+
self.board = board
98+
99+
def set_path(self, path):
100+
"""
101+
102+
Set the path attribute of the instance.
103+
104+
Parameters
105+
----------
106+
self : object
107+
The instance of the class from which this method is called.
108+
109+
path : list of tuples/lists
110+
The path to be set for the instance, typically a list of positions.
111+
112+
Returns
113+
-------
114+
None
115+
116+
"""
117+
self.path = path
118+
119+
def run(self):
120+
"""
121+
122+
Start the main event loop of the application.
123+
124+
This method calls the main_loop function, passing the current instance as an argument.
125+
126+
Parameters
127+
----------
128+
self : object
129+
The instance of the class from which this method is called.
130+
131+
Returns
132+
-------
133+
None
134+
135+
"""
136+
main_loop(self)
137+
138+
def draw(self, surface):
139+
"""
140+
Draw the board and path on the given surface.
141+
142+
This method draws the board on the provided surface. If a path is set, it also draws the path.
143+
144+
Parameters
145+
----------
146+
self : object
147+
The instance of the class from which this method is called.
148+
149+
surface : pygame.Surface
150+
The Pygame surface on which the board and path will be drawn.
151+
152+
Returns
153+
-------
154+
None
155+
156+
"""
157+
if self.board == None:
158+
return
159+
160+
draw_board(surface, surface.get_rect(), self.board)
161+
if self.path != None:
162+
draw_path(surface, surface.get_rect(), self.board, self.path)
163+
164+
165+
class BoardMetrics:
166+
def __init__(self, area, board):
167+
self.area = area #area of the board which is surface.rect() object rect<x,y,w,h> board is what we created in my_maze.py
168+
self.spacing = 3 #spacing for cell's and board
169+
self.left = area[0] + self.spacing #left is starting position of cell 1 with spacing
170+
self.top = area[1] + self.spacing # same for left but for top side
171+
self.height = area[3] - area[1] - 2 * self.spacing #height of board - 2 spacing from each side
172+
self.width = area[2] - area[0] - 2 * self.spacing #width of board - 2 spacing from each side
173+
self.num_y = board.get_size()[1] #board height with number of rows[[][]---]
174+
self.num_x = board.get_size()[0] #board width with number of columns[[1,2,3,4...]]
175+
self.cx = self.width / self.num_x #cell's x found by dividing width of board to num of cell's
176+
self.cy = self.height / self.num_y #cell's y found by dividing height of board to num of cell's
177+
178+
179+
def cell_rect(self, pos):
180+
"""
181+
182+
This function takes position and returns rectangle object at that position as a list with its [x,y,w,h]
183+
184+
Parameters:
185+
-----------
186+
pos (list): This parameter represents the position of the cell.
187+
188+
Returns:
189+
--------
190+
list:
191+
The new x-coordinate of the rectangle's top-left corner.
192+
The new y-coordinate of the rectangle's top-left corner.
193+
The original width of the rectangle.
194+
The original height of the rectangle.
195+
196+
"""
197+
return [self.left + pos[0]*self.cx, self.top + pos[1]*self.cy, self.cx - self.spacing, self.cy - self.spacing]
198+
199+
def cell_center(self, pos):
200+
"""
201+
202+
This function takes position and returns position of cell's center as a list
203+
204+
Parameters:
205+
-----------
206+
pos (list): This parameter represents the position of the cell
207+
208+
Returns:
209+
--------
210+
list:
211+
x-coordinate of rectangle's center
212+
y-coordinate of rectangle's center
213+
214+
"""
215+
rct = self.cell_rect(pos)
216+
return [rct[0]+rct[2]/2, rct[1] + rct[3]/2]
217+
218+
def draw_board(surface, area, board):
219+
"""
220+
221+
This function takes board and draws it on surface.
222+
223+
Parameters:
224+
-----------
225+
surface (pygame.Surface): This parameter represents the surface on which the board will be drawn.
226+
227+
area (list): This parameter represents the area of the board.
228+
229+
board (my_maze.Board): This parameter represents the board.
230+
231+
Returns:
232+
--------
233+
None
234+
235+
"""
236+
pygame.draw.rect(surface, (0, 0, 0), area)
237+
metrics = BoardMetrics(area, board)
238+
239+
colors = {
240+
241+
my_maze.CellType.Empty : (40, 40, 40),
242+
my_maze.CellType.Block : (128, 79, 179)
243+
}
244+
245+
marks = {
246+
my_maze.CellMark.Start : (0, 204, 152),
247+
my_maze.CellMark.End : (153, 0, 102)
248+
}
249+
for iy in range(metrics.num_y):
250+
for ix in range(metrics.num_x):
251+
cell = board.at([ix, iy])
252+
clr = colors.get(cell.type, (129, 100, 0))
253+
cell_rect = metrics.cell_rect( [ix, iy] )
254+
255+
pygame.draw.rect(surface, clr, cell_rect)
256+
257+
if cell.count != math.inf:
258+
number = cell_font.render( "{}".format(cell.count), True, (255,255,255))
259+
surface.blit(number, trans_rect(number.get_rect(),
260+
[cell_rect[0] + (cell_rect[2] - number.get_rect()[2])/2,
261+
cell_rect[1] + (cell_rect[3] -number.get_rect()[3])/2]
262+
))
263+
264+
mark = marks.get(cell.mark, None)
265+
if mark != None:
266+
pygame.draw.rect(surface, mark, cell_rect, metrics.spacing)
267+
268+
269+
def draw_path(surface, area, board, path):
270+
"""
271+
272+
This function takes board and draws it on surface.
273+
274+
Parameters:
275+
----------
276+
surface (pygame.Surface): This parameter represents the surface on which the board will be drawn.
277+
278+
area (list): This parameter represents the area of the board.
279+
280+
board (my_maze.Board): This parameter represents the board.
281+
282+
path (list): This parameter represents the path.
283+
284+
Returns:
285+
--------
286+
None
287+
288+
"""
289+
metrics = BoardMetrics(area, board)
290+
for i in range(len(path)-1):
291+
center_a = metrics.cell_center(path[i].pos)
292+
center_b = metrics.cell_center(path[i+1].pos)
293+
pygame.draw.line(surface, (1, 99, 148), center_a, center_b, metrics.spacing )
294+
295+
296+
297+
298+
299+

0 commit comments

Comments
 (0)