116 lines
4.0 KiB
Python
116 lines
4.0 KiB
Python
|
# 判断当前节点是否可以拓展并加入开放列表
|
|||
|
def validNode(open_list, open_parent_node, g, x, y, x_expand, y_expand, min_idx):
|
|||
|
if maze[x_expand][y_expand] == '0' or maze[x_expand][y_expand] == 'E':
|
|||
|
if [x_expand, y_expand] in open_list:
|
|||
|
idx = open_list.index([x_expand, y_expand])
|
|||
|
if g[idx] < g[min_idx] + 1:
|
|||
|
g[idx] = g[min_idx] + 1
|
|||
|
open_parent_node[idx] = [x,y]
|
|||
|
else:
|
|||
|
open_list.append([x_expand,y_expand])
|
|||
|
open_parent_node.append([x,y])
|
|||
|
g.append(g[min_idx]+1)
|
|||
|
|
|||
|
|
|||
|
# 拓展开放列表中的节点,启发函数为Lp距离
|
|||
|
def expandNode(open_list, close_list, open_parent_node, close_parent_node, g):
|
|||
|
min_cost = 100000 # 当前最小开销
|
|||
|
min_idx = 0 # 开销最小的节点的下标
|
|||
|
p = 1 # Lp距离的p
|
|||
|
|
|||
|
# 找到可扩展的开销最小的节点
|
|||
|
for i in range(len(open_list)):
|
|||
|
h = (abs(open_list[i][0] - end_node[0])**p + abs(open_list[i][1] - end_node[1])**p ) ** (1/p)
|
|||
|
# h = max(abs(open_list[i][0] - end_node[0]), abs(open_list[i][1] - end_node[1]))
|
|||
|
# h = 0
|
|||
|
h *= 4
|
|||
|
f = h + g[i]
|
|||
|
if f < min_cost:
|
|||
|
min_cost = f
|
|||
|
min_idx = i
|
|||
|
|
|||
|
# 将该节点的可扩展节点加入开放列表
|
|||
|
x = open_list[min_idx][0]
|
|||
|
y = open_list[min_idx][1]
|
|||
|
maze[x][y] = '1'
|
|||
|
validNode(open_list, open_parent_node, g, x, y, x+1, y, min_idx)
|
|||
|
validNode(open_list, open_parent_node, g, x, y, x-1, y, min_idx)
|
|||
|
validNode(open_list, open_parent_node, g, x, y, x, y+1, min_idx)
|
|||
|
validNode(open_list, open_parent_node, g, x, y, x, y-1, min_idx)
|
|||
|
print(len(open_list))
|
|||
|
# 将该节点从开放列表中删除并加入关闭列表
|
|||
|
close_list.append([x,y])
|
|||
|
close_parent_node.append(open_parent_node[min_idx])
|
|||
|
expanded.add((x,y))
|
|||
|
del open_list[min_idx]
|
|||
|
del open_parent_node[min_idx]
|
|||
|
del g[min_idx]
|
|||
|
|
|||
|
# 读入迷宫数据
|
|||
|
maze = []
|
|||
|
with open('MazeData.txt', 'r') as f:
|
|||
|
for eachLine in f:
|
|||
|
line = []
|
|||
|
for eachPos in eachLine:
|
|||
|
if eachPos == '\n':
|
|||
|
break
|
|||
|
line.append(eachPos)
|
|||
|
maze.append(line)
|
|||
|
|
|||
|
# 找到起点和终点坐标,并加入开启列表
|
|||
|
row = len(maze)
|
|||
|
col = len(maze[0])
|
|||
|
open_list = [] # 开启列表
|
|||
|
open_parent_node = [None] # 开启列表中每个节点对应的父节点
|
|||
|
g = [0] # 开启列表中每个节点对应的 g(x) 值
|
|||
|
close_list = [] # 关闭列表
|
|||
|
close_parent_node = [] # 关闭列表中每个节点对应的父节点
|
|||
|
end_node = []
|
|||
|
expanded = set()
|
|||
|
for i in range(row):
|
|||
|
for j in range(col):
|
|||
|
if maze[i][j] == 'S':
|
|||
|
open_list.append([i,j])
|
|||
|
if maze[i][j] == 'E':
|
|||
|
end_node = [i,j]
|
|||
|
|
|||
|
# 开始搜索
|
|||
|
find_ans = False
|
|||
|
while 1:
|
|||
|
# 若开启列表为空,则迷宫无解
|
|||
|
if open_list == []:
|
|||
|
find_ans = False
|
|||
|
break
|
|||
|
# 对节点进行拓展
|
|||
|
expandNode(open_list, close_list, open_parent_node, close_parent_node, g)
|
|||
|
# 若开放节点中存在终点节点则找到解
|
|||
|
if end_node in open_list:
|
|||
|
find_ans = True
|
|||
|
break
|
|||
|
|
|||
|
if find_ans == False:
|
|||
|
print('no answer for this maze')
|
|||
|
else:
|
|||
|
idx = open_list.index(end_node)
|
|||
|
last_node = open_parent_node[idx]
|
|||
|
path = [end_node]
|
|||
|
while last_node is not None:
|
|||
|
path.append(last_node)
|
|||
|
last_node = close_parent_node[close_list.index(last_node)]
|
|||
|
path = path[::-1]
|
|||
|
print(len(expanded) + 1)
|
|||
|
print(len(path))
|
|||
|
print(path)
|
|||
|
# maze = []
|
|||
|
# with open('MazeData.txt', 'r') as f:
|
|||
|
# for eachLine in f:
|
|||
|
# maze.append(eachLine)
|
|||
|
# for i in range(row):
|
|||
|
# for j in range(col):
|
|||
|
# if [i,j] in path:
|
|||
|
# if (i,j) in expanded:
|
|||
|
# maze[i] = maze[i][:j] + 'X' + maze[i][j+1:]
|
|||
|
# with open('ans.txt', 'w') as f:
|
|||
|
# for eachLine in maze:
|
|||
|
# f.write(eachLine)
|