-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsolver.py
More file actions
193 lines (152 loc) · 5.05 KB
/
solver.py
File metadata and controls
193 lines (152 loc) · 5.05 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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
###########################################################################################################
# arguments:
# python solver.py arg1
# arg1 - maze filename. The result will be printed in a new file filename_solved.png
###########################################################################################################
from time import sleep
from PIL import Image
from enum import Enum
import numpy, sys
COLOR_BLACK = numpy.array([0, 0, 0, 255])
COLOR_WHITE = numpy.array([255, 255, 255, 255])
COLOR_GREEN = numpy.array([0, 255, 0, 255])
COLOR_RED = numpy.array([255, 0, 0, 255])
COLOR_BLUE = numpy.array([0, 0, 255, 255])
class Type(Enum):
FREE= 0
WALL= 1
START= 2
END= 3
class Tile():
def __init__(self, position, type=Type.FREE):
self.position = position
self.g_value = float('inf')
self.f_value = float('inf')
self.type = type
self.parent = None
def getG(self):
return self.g_value
def getF(self):
return self.f_value
def setG(self, g):
self.g_value = g
def setF(self, f):
self.f_value = f
def getPosition(self):
return self.position
def getX(self):
return self.position[0]
def getY(self):
return self.position[1]
def getType(self):
return self.type
def setParent(self, parent):
self.parent = parent
def getParent(self):
return self.parent
def __str__(self):
if self.getType() == Type.FREE:
return ' '
elif self.getType() == Type.WALL:
return 'X'
elif self.getType() == Type.START:
return 'S'
elif self.getType() == Type.END:
return 'E'
def __eq__(self, obj):
return obj.getPosition() == self.getPosition()
def return_path(last_tile):
path = []
current = last_tile
while current is not None:
path.append(current.position)
current = current.getParent()
return path[::-1]
def heuristic(nearby, endTile):
return abs(nearby.getX() - endTile.getX()) + abs(nearby.getY() - endTile.getY())
def findRoute(map, startTile, endTile, x_bound, y_bound):
neighbors = ((0, -1), (0, 1), (-1, 0), (1, 0),(-1, -1), (1,1), (-1, 1), (1, -1))
open_list = []
closed_list = []
startTile.setG(0)
startTile.setF(heuristic(startTile, endTile))
open_list.append(startTile)
while len(open_list) != 0:
current = open_list[0]
curr_id = 0
for id, obj in enumerate(open_list):
if obj.getF() < current.getF():
current = obj
curr_id = id
open_list.pop(curr_id)
closed_list.append(current)
if current == endTile:
print('Found solution!')
return return_path(current)
nearbyTiles = []
for offset in neighbors:
new_pos = (current.getX() + offset[0], current.getY() + offset[1])
if new_pos[0] >= x_bound or new_pos[0] < 0 or new_pos[1] >= y_bound or new_pos[1] < 0:
continue
newTile = map[new_pos[1]][new_pos[0]]
if newTile.getType() == Type.WALL:
continue
nearbyTiles.append(newTile)
for nearby in nearbyTiles:
temp_g = current.getG() + 1
if temp_g < nearby.getG():
nearby.setParent(current)
nearby.setG(temp_g)
nearby.setF(nearby.getG() + heuristic(nearby, endTile))
if len([tile for tile in open_list if nearby == tile]) == 0:
open_list.append(nearby)
print('No results')
return []
def main():
map = []
x = 0
y = 0
startTile = None
endTile = None
try:
img = Image.open(sys.argv[1])
except:
print(f"[ERROR!] Not a valid image found in file: {sys.argv[1]}")
return
np_img = numpy.array(img)
for row in np_img:
x = 0
tmp = []
for col in row:
if (col == COLOR_WHITE).all():
tmp.append(Tile((x, y), Type.FREE))
elif (col == COLOR_BLACK).all():
tmp.append(Tile((x, y), Type.WALL))
elif (col == COLOR_GREEN).all():
startTile = Tile((x, y), Type.START)
tmp.append(startTile)
elif (col == COLOR_RED).all():
endTile = Tile((x, y), Type.END)
tmp.append(endTile)
else:
print('Err')
return
x+=1
map.append(tmp)
y+=1
print(f'Read image {x}x{y}')
for row in map:
for col in row:
print(col, end='')
print()
path = findRoute(map, startTile, endTile, x, y)
print('Path:')
for index, node in enumerate(path):
if index != 0 and index != len(path)-1:
np_img[node[1]][node[0]] = COLOR_BLUE
print(node)
im = Image.fromarray(np_img)
filename = (sys.argv[1]).rsplit('.', 1)[0]
im.save(filename+"_solved.png")
if __name__ == '__main__':
main()