def __a_star_visualize(): global flag, depth, count, _tracked, _untracked, _page, _end_pos if not len(_untracked): ip = InfoPage(_page, "searching failed!") ip.show() flag = False _page.a_star_timer.stop() # 弹出总消耗(G+H)最小的当前地图 temp = _untracked[0].copy() # 加入已经探索的列表 _tracked.append(_untracked.pop(0)) count += 1 _page.numbers = temp.get("map") _page.updateBlocks() _page.updatePanel() # 如果到达目标则跳出 if ef.compare(temp.get("map"), _end_pos): flag = True ip = InfoPage( _page, "Training Success In ASTAR!\n" "begin:\n" + ef.as_str(_page.begin) + "visited nodes: " + str(count) + "\n") ip.show() _page.a_star_timer.stop() return # 若果超过探索深度的限制也跳出 if temp.get("G") > depth: return maybe = [] # 在当前情况的基础下,所有可能出现的情形 idx = 0 while idx < 4: mmp = temp.get("map") # 如果可以朝哪个方向移动,将移动后的情形加入栈 if ef.can_motion[idx](mmp): pos = ef.motion[idx](mmp) maybe.append({ "map": pos, "G": temp.get("G") + 1, # 实际的步数在已有的步数上加一 "parent": mmp, "H": H(pos, _end_pos) }) # 预测到最后的步数 idx += 1 for mp1 in maybe: # 如果已经探索,则什么操作也不做 if in_list(mp1, _tracked): continue for idx, mp2 in enumerate(_untracked): if ef.compare(mp2.get("map"), mp1.get("map")): # 如果已经发现,判断G消耗之间的关系,如果小则替代掉,反之则什么也不做 if mp1.get("G") > mp2.get("G"): _untracked[idx] = mp2.copy() break else: # 如果当前节点没有被发现,则加入发现列表 _untracked.append(mp1) _untracked.sort(key=F) # 按照总消耗进行升序
def backtrack(b, e): global flag, count count = 0 print("searching backtrack ...") flag = False m = {"map": b, "parent": None} temp = __backtrack(m, e, 0) out_asr = [] if flag: asr = [temp.get("map")] p = temp.get("parent") while p is not None: for i in tracked: if ef.compare(p, i.get("map")): asr.append(i.get("map")) p = i.get("parent") break out_asr = asr.copy() print("answer: ") while len(asr): ef.printMap(asr.pop()) print() else: print(flag) return out_asr
def in_list(mp, lst): """ 判断一个地图的值是否在列表中 :param mp: 需要判断的地图 :param lst: 目标列表 :return: 是否存在 """ for mp1 in lst: if ef.compare(mp.get("map"), mp1.get("map")): return True else: return False
def __backtrack(b, e, depth): """ 回溯算法递归函数 :param b: 当前情形 :param e: 结束情形 :param depth: 当前搜索的步数 :return: 结果节点 """ global flag, tracked, count count += 1 # 如果结果一致,则弹出 if ef.compare(b.get("map"), e): flag = True return b # 到达最大搜索路径 if depth >= max_depth: return None if in_tracked(b): return None else: tracked.append(b) pos = b nxt_pos = [] idx = 0 while idx < 4: mmp = pos.get("map") # 如果可以朝哪个方向移动,将移动后的情形加入栈 if ef.can_motion[idx](mmp): nxt_pos.append({"map": ef.motion[idx](mmp), "parent": mmp}) idx += 1 # 对于所有可能出现的情况,都进行一次递归 for i in nxt_pos: asr = __backtrack(i, e, depth + 1) # 如果找到结果 if flag: return asr # 没找到结果返回当前节点 return b
def in_list(mp, lst): for mp1 in lst: if ef.compare(mp.get("map"), mp1.get("map")): return True else: return False
def dfs(b: list, e: list): """ 深度优先算法 :param b: 初始情形 :param e: 结束情形 :return: 一个列表,包含从 b->e 的一个解法 """ global count, flag print("searching dfs ...") mp = { "map": b, "depth": 0, "parent": None } # 最初的情形,深度用于判断是否跳出,parent用于最后超出所有路径 end_pos = e # 结束节点 depth = ef.mp_size * ef.mp_size # 探索的最大深度 untracked = [] # 维护一个所有没探索过节点的栈 tracked = [] # 维护一个所有已经探索过节点的栈 untracked.append(mp) out_asr = [] # 输出的结果 temp = None flag = False count = 0 # 当还有没探索过的节点时 while len(untracked): # 探索栈内最后的节点 temp = untracked[-1].copy() tracked.append(untracked.pop()) count += 1 # 如果到达目标则跳出 if ef.compare(temp.get("map"), end_pos): flag = True break # 若果超过探索深度的限制也跳出 if temp.get("depth") > depth: continue maybe = [] # 在当前情况的基础下,所有可能出现的情形 idx = 0 while idx < 4: mmp = temp.get("map") # 如果可以朝哪个方向移动,将移动后的情形加入栈 if ef.can_motion[idx](mmp): maybe.append({ "map": ef.motion[idx](mmp), "depth": temp.get("depth") + 1, "parent": mmp }) idx += 1 # 如果可能出现的情形并没有在未探索栈中且未在已探索栈中,则加入未探索栈 for mb in maybe: if not in_list(mb, untracked): if not in_list(mb, tracked): untracked.append(mb.copy()) # 如果找到通路,则输出 if flag: asr = [temp.get("map")] p = temp.get("parent") while p is not None: for i in tracked: if ef.compare(p, i.get("map")): asr.append(i.get("map")) p = i.get("parent") break print("answer: ") out_asr = asr.copy() while len(asr): ef.printMap(asr.pop()) print() else: print(flag) return out_asr
def in_tracked(map1): for mp in tracked: if ef.compare(mp.get("map"), map1.get("map")): return True else: return False
def a_star(b, e): """ a_star 算法的实现 :param b: 开始的地图 :param e: 目标地图 :return: 存有解题过程的栈 """ global flag, depth, count print("searching A-Star ...") flag = False count = 0 mp = {"map": b, "G": 0, "parent": None, "H": H(b, e)} end_pos = e untracked = [mp.copy()] # 所有已经发现但还没有探索过的节点 tracked = [] # 记录所有已经发现且已经探索过的节点 temp = None # 当前正在操作的节点 while len(untracked): # 弹出总消耗(G+H)最小的当前地图 temp = untracked[0].copy() # 加入已经探索的列表 tracked.append(untracked.pop(0)) count += 1 # 如果到达目标则跳出 if ef.compare(temp.get("map"), end_pos): flag = True break # 若果超过探索深度的限制也跳出 if temp.get("G") > depth: continue maybe = [] # 在当前情况的基础下,所有可能出现的情形 idx = 0 while idx < 4: mmp = temp.get("map") # 如果可以朝哪个方向移动,将移动后的情形加入栈 if ef.can_motion[idx](mmp): pos = ef.motion[idx](mmp) maybe.append({ "map": pos, "G": temp.get("G") + 1, # 实际的步数在已有的步数上加一 "parent": mmp, "H": H(pos, e) }) # 预测到最后的步数 idx += 1 for mp1 in maybe: # 如果已经探索,则什么操作也不做 if in_list(mp1, tracked): continue for idx, mp2 in enumerate(untracked): if ef.compare(mp2.get("map"), mp1.get("map")): # 如果已经发现,判断G消耗之间的关系,如果小则替代掉,反之则什么也不做 if mp1.get("G") > mp2.get("G"): untracked[idx] = mp2.copy() break else: # 如果当前节点没有被发现,则加入发现列表 untracked.append(mp1) untracked.sort(key=F) # 按照总消耗进行升序 out_asr = [] # 如果找到通路,则输出 if flag: asr = [temp.get("map")] # 通过父节点进行判断 p = temp.get("parent") while p is not None: for i in tracked: if ef.compare(p, i.get("map")): asr.append(i.get("map")) p = i.get("parent") break print("answer: ") out_asr = asr.copy() while len(asr): ef.printMap(asr.pop()) print() else: print(flag) return out_asr
def bfs(b, e): """ 宽度优先搜索实现 :param b: 起始状态 :param e: 结束状态 :return: 一个包含路径的栈 """ global count, flag print("searching bfs ...") mp = { "map": b, "board": 0, "parent": None } # 最初的情形,宽度用于判断是否跳出,parent用于最后输出所有路径 end_pos = e # 结束节点 board = ef.mp_size * ef.mp_size # 探索的最大深度 untracked = [] # 维护一个所有没探索过节点的队列 tracked = [] # 维护一个所有已经探索过节点的队列 untracked.append(mp) out_asr = [] # 输出的结果 temp = None flag = False count = 0 # 当还有没探索过的节点时 while len(untracked): # 探索队列内第一个节点 temp = untracked[0].copy() tracked.append(untracked.pop(0)) count += 1 # 如果到达目标则跳出 if ef.compare(temp.get("map"), end_pos): flag = True break # 若果超过探索宽度的限制也跳出 if temp.get("board") > board: continue maybe = [] # 在当前情况的基础下,所有可能出现的情形 idx = 0 while idx < 4: mmp = temp.get("map") # 如果可以朝哪个方向移动,将移动后的情形加入队列 if ef.can_motion[idx](mmp): maybe.append({ "map": ef.motion[idx](mmp), "board": temp.get("board") + 1, "parent": mmp }) idx += 1 # 如果可能出现的情形并没有在未探索队列中且未在已探索队列中,则加入未探索队列 for mb in maybe: if not in_list(mb, untracked): if not in_list(mb, tracked): untracked.append(mb.copy()) # 如果找到通路,则输出 if flag: asr = [temp.get("map")] p = temp.get("parent") while p is not None: for i in tracked: if ef.compare(p, i.get("map")): asr.append(i.get("map")) p = i.get("parent") break print("answer: ") out_asr = asr.copy() while len(asr): ef.printMap(asr.pop()) print() else: print(flag) return out_asr