3 Zaimplementuj algorytm znalezienia najkrótszej ścieżki w labiryncie na podstawie algorytmu Źródło: http://www.unit1.pl/349,txt (2018-02-12)
In [ ]:
from collections import namedtuple, deque
Point = namedtuple("Point", "x y")
_wall = object()
maze = [
[-1, -1, -1, -1],
[-1, _wall, -1, -1],
[-1, _wall, -1, -1],
[-1, -1, _wall, -1]
]
expected_result = [
Point(0, 0),
Point(0, 1),
Point(1, 2),
Point(2, 3),
Point(3, 3)
]
expected_result2 = [
Point(0, 0),
Point(0, 1),
Point(1, 2),
Point(2, 2),
Point(3, 3)
]
In [ ]:
def shortest_path(maze, starting_point, exit_point):
que = deque()
maze[starting_point.x][starting_point.y] = 0
que.append(starting_point)
while len(que):
point = que.popleft()
neighbours = _find_neighbours(maze, point)
not_visited = _filter_visited(maze, neighbours)
if _increment_neighbors_value(maze, point, not_visited, exit_point):
return _get_path(maze, exit_point, starting_point)
que.extend(not_visited)
def _find_neighbours(maze, tested_point):
maze_length = len(maze)
point_x = tested_point.x
point_y = tested_point.y
points = (Point(x, y) for x in range(point_x - 1, point_x + 2) for y in range(point_y - 1, point_y + 2))
result = []
for point in points:
if (point.x >= 0 and point.y >= 0
and point.y < maze_length
and point.x < maze_length
and point != tested_point
and _point_not_a_wall(maze, point)):
result.append(point)
return result
def _point_value(maze, point):
return maze[point.x][point.y]
def _point_not_a_wall(maze, point):
return _point_value(maze, point) != _wall
def _filter_visited(maze, points):
return [point for point in points if _point_value(maze, point) == -1]
def _increment_neighbors_value(maze, point, neighbours, exit_point):
value = _point_value(maze, point)
for p in neighbours:
maze[p.x][p.y] = value + 1
if p == exit_point:
return True
return False
def _get_path(maze, exit_point, starting_point):
result = [exit_point]
que = deque([exit_point])
while que:
point = que.popleft()
value = _point_value(maze, point)
neighbours = _find_neighbours(maze, point)
for neighbour in neighbours:
if neighbour == starting_point:
result.append(neighbour)
break
if _point_value(maze, neighbour) == value - 1:
result.append(neighbour)
que.append(neighbour)
break
return list(reversed(result))
result = shortest_path(maze, Point(0, 0), Point(3, 3))
assert result == expected_result or result == expected_result2