Пример #1
0
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)  # 按照总消耗进行升序
Пример #2
0
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
Пример #3
0
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
Пример #4
0
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
Пример #5
0
def in_list(mp, lst):
    for mp1 in lst:
        if ef.compare(mp.get("map"), mp1.get("map")):
            return True
    else:
        return False
Пример #6
0
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
Пример #7
0
def in_tracked(map1):
    for mp in tracked:
        if ef.compare(mp.get("map"), map1.get("map")):
            return True
    else:
        return False
Пример #8
0
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
Пример #9
0
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