This repository was archived by the owner on May 19, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmaze.py
More file actions
154 lines (110 loc) · 4.29 KB
/
Copy pathmaze.py
File metadata and controls
154 lines (110 loc) · 4.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
from queue import Queue
import graph.impl
from graph.abstract import *
REGULAR = 1
WALL = 2
START = 3
FINISH = 4
PATH = 5
class Cell(Hashable):
def __init__(self, i, j, kind):
self.i = i
self.j = j
self.kind = kind
def __hash__(self):
return hash(repr(self))
def __eq__(self, other):
return type(other) is Cell and self.__dict__ == other.__dict__
def __repr__(self):
return '(%d, %d, %d)' % (self.i, self.j, self.kind)
class Maze:
def __init__(self, i_size, j_size, graph_impl=None):
self.i_size = i_size
self.j_size = j_size
self._start = None
self._finish = None
self.graph = graph_impl or graph.impl.AdjacencyMap()
self.index_map = {}
for i in range(i_size):
for j in range(j_size):
current = self.graph.create_vertex(Cell(i, j, REGULAR))
if i != 0:
upper = Vertex(self.cell_for_index(i - 1, j))
self.graph.connect(EdgeType.undirected, current, upper, 1)
if j != 0:
left = Vertex(self.cell_for_index(i, j - 1))
self.graph.connect(EdgeType.undirected, current, left, 1)
start = property()
@start.getter
def start(self):
return self._start
@start.setter
def start(self, new_start):
if self._start:
self.set(self._start, REGULAR)
self._start = self.set(new_start, START)
finish = property()
@finish.getter
def finish(self):
return self._finish
@finish.setter
def finish(self, new_finish):
if self._finish:
self.set(self._finish, REGULAR)
self._finish = self.set(new_finish, FINISH)
def cell_for_index(self, i_key, j_key):
for vertex in self.graph.vertices():
cell = vertex.data
if cell.i == i_key and cell.j == j_key:
return cell
return None
def set(self, target_cell, new_kind):
for old_vertex in self.graph.vertices():
cell = old_vertex.data
if cell == target_cell:
if cell.kind == new_kind:
return cell
# Preventing case where internal _start / _finish
# variable holds cell which was redefined with
# different kind.
if target_cell == self._start \
and new_kind != START:
self._start = None
elif target_cell == self._finish \
and new_kind != FINISH:
self._finish = None
old_neighbours = self.graph[old_vertex]
del self.graph[old_vertex]
new_vertex = self.graph.create_vertex(Cell(cell.i, cell.j,
new_kind))
for connection in old_neighbours:
connection.src = new_vertex
self.graph[new_vertex] = old_neighbours
for neighbour in [conn.dst for conn in old_neighbours]:
# Graph implementation should to get rid of all
# edges directed to the old_vertex on del self.graph[old_vertex] call
self.graph[neighbour].append(Edge(neighbour, new_vertex, 1))
return new_vertex.data
def bfs_path(self, source, destination):
source, destination = Vertex(source), Vertex(destination)
unexplored = Queue()
unexplored.put(source)
visits = {}
while not unexplored.empty():
current = unexplored.get()
if current == destination:
wayback = []
while current != source:
current = visits[current].src
wayback.append(current)
# Start is not part of the path,
# neither finish is.
return [v.data for v in reversed(wayback[:-1])]
neighbours = self.graph[current]
for conn in neighbours:
if conn.dst.data.kind == WALL:
continue
if conn.dst not in visits:
visits[conn.dst] = conn
unexplored.put(conn.dst)
return None