A * найти путь к Maze1, 2, 3 - PullRequest
       12

A * найти путь к Maze1, 2, 3

2 голосов
/ 05 ноября 2019

Я пытаюсь закодировать алгоритм, который находит путь Лабиринтов, используя A * Algo. Но я не получаю путь при печати. В чем дело? это то, что у меня есть:

basic_operations = 0

def findStart(maze):
    for i in range(len(maze)):
        for j in range(len(maze[0])):
            if maze[i][j] == 'P':
                return tuple([i, j])
    return None


def findEnd(maze):
    for i in range(len(maze)):
        for j in range(len(maze[0])):
            if maze[i][j] == '.':
                return tuple([i, j])
    return None


def readMazeFromFile(f):
    maze = list()
    with open(f) as file:
        for line in file:
            maze.append(list(line.rstrip()))
    return maze


def printMaze(maze):
    for i in range(len(maze)):
        for j in range(len(maze[0])):
            print(maze[i][j], end="")
        print()


def printPath(maze, path):
    for i in range(len(maze)):
        for j in range(len(maze[0])):
            if tuple([i, j]) in path and maze[i][j] != 'P' and maze[i][j] != '.':
                print("x", end="")
            else:
                print(maze[i][j], end="")
        print()


class Node():
    """A node class for A* Pathfinding"""

    def __init__(self, parent=None, position=None):
        self.parent = parent
        self.position = position

        self.g = 0
        self.h = 0
        self.f = 0

    def __eq__(self, other):
        return self.position == other.position


def astar(maze, start, end):
    """Returns a list of tuples as a path from the given start to the given end in the given maze"""

    # Create start and end node
    start_node = Node(None, start)

    start_node.g = start_node.h = start_node.f = 0
    end_node = Node(None, end)
    end_node.g = end_node.h = end_node.f = 0

    # Initialize both open and closed list
    open_list = []
    closed_list = []

    # Add the start node
    open_list.append(start_node)

    # Loop until you find the end
    while len(open_list) > 0:

        # Get the current node
        current_node = open_list[0]
        current_index = 0
        for index, item in enumerate(open_list):
            if item.f < current_node.f:
                current_node = item
                current_index = index

        # Pop current off open list, add to closed list
        open_list.pop(current_index)
        closed_list.append(current_node)

        # Found the goal
        if current_node == end_node:
            path = []
            current = current_node
            while current is not None:
                path.append(current.position)
                current = current.parent
            return path[::-1]  # Return reversed path

        # Generate children
        children = []
        # Adjacent squares
        for new_position in [(0, -1), (0, 1), (-1, 0), (1, 0), (-1, -1), (-1, 1), (1, -1), (1, 1)]:

            # Get node position
            node_position = (
                current_node.position[0] + new_position[0], current_node.position[1] + new_position[1])

            # Make sure within range
            if node_position[0] > (len(maze) - 1) or node_position[0] < 0 or node_position[1] > (
                    len(maze[len(maze) - 1]) - 1) or node_position[1] < 0:
                continue

            # Make sure walkable terrain
            if maze[node_position[0]][node_position[1]] != 0:
                continue

            # Create new node
            new_node = Node(current_node, node_position)

            # Append
            children.append(new_node)

        # Loop through children
        for child in children:

            # Child is on the closed list
            for closed_child in closed_list:
                if child == closed_child:
                    continue

            # Create the f, g, and h values
            child.g = current_node.g + 1
            child.h = ((child.position[0] - end_node.position[0]) **
                       2) + ((child.position[1] - end_node.position[1]) ** 2)
            child.f = child.g + child.h

            # Child is already in the open list
            for open_node in open_list:
                if child == open_node and child.g > open_node.g:
                    continue

            # Add the child to the open list
            open_list.append(child)



    return None


def main():
    i = 0

    for file in os.listdir():
        if file.startswith("Maze") and file.endswith(".txt"):
            i += 1
            # Print file reading
            print("Maze", i)

            maze = readMazeFromFile(file)
            start = findStart(maze)
            end = findEnd(maze)

            startTime = time.time()
            # Give values to BFS to start traversing
            path = astar(maze, start, end)
            endTime = time.time()

            if path == None:
                printMaze(maze)
                print("No path to destination.")
            else:
                printPath(maze, path)
                print("Shortest path: ")
                print(path)

            print("Time taken:", endTime - startTime, "secs")
            print("Basic operations: ", basic_operations)
            print("\n")


if __name__ == '__main__':
    main()

Это один из лабиринтов (в текстовых файлах):

Maze1 (P - начальная точка):

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%     %       %             %         %     %           %   %
%%% %%% %%%%%   %%%%% %%%%% %%% %%%%%%% % %%% %%%%%%%%%%% %%%
%   %   %     %   % %   % %   %         %          % % %    %
% %%% %%% %%% %%% % %%% % %%% % %%%%%% %%%%% %%%%% % % %%%% %
% %   % %   % %   %   % % % % %     %        %   % % %      %
%   %%% % % % % % % % %%% % % % %%% % %%%% % %%% % % %% % % %
% %   %   % %   %   % %   % %     % % %  % %     % %  %%% % %
% %%%%%%% % % %%% %%% %%%   %%% %%% % % %% %%%%% %%%% % % % %
%   %   % %       % % %   % % %  %  % %  %    %     %   % % %
% % %%% % %%%%%%%%% % % %%% % %  % %% %% % %%%%%%%%%%% %%%% %
% %   % %   %       %%% %     %  %    %  %      %           %
% % %%% %%%%% %%%%%   % %%%%%%%% %%% %%% % %% %%% %%%%%%% % %
% %   %       %     %   %        %     % %  %   %     %   % %
% %%%%%%% %%%%% %%%%% % %%%%% %%%%%%%%%% % %%%%%% %%% %%% % %
% % %     %     %   % %             %    %    %   %     % % %
%   %%% %%% %%%%%%% %%%%% %%%%%%% %%% %% %%%  % %%% %%% %%% %
% %   %   %       % %     %            %   %    %     %   % %
% %%%%% % %%%%%%% %%%%%%% %%%%%%%% %%% % %%%%%% % % %%%%% % %
%.%     %   %     %       %   %    %   %        % % %   % % %
%%%%%% %% % % %%%%% %%%%% %%% % %%%% %%%%%%%%%%%%%%%% %%% % %
%P        % %           %     %           %           %     %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

Это то, чего я пытался достичь:

// A * Алгоритм поиска 1. Инициализируйте открытый список 2. Инициализируйте закрытый список, поместите начальный узел в открытый список (вы можете оставить его f в нуле. )

пока открытый список не пустой а) найти узел с наименьшим f в открытом списке, назовите его "q"

b) вывести q из открытого списка

в) сгенерировать 8 наследников q и установить для их родителей значение q

d) для каждого преемника i) если преемник является целью, прекратить поиск successor.g = qg + расстояние между преемником и q successor.h =расстояние от цели до преемника (это можно сделать разными способами, мы обсудим три эвристики - эвристику Манхэттена, Евклида и Диагонали)

successor.f = successor.g + successor.h

ii) если узел с той же позицией, что и преемник, находится в списке ОТКРЫТО, у которого значение f ниже, чем у преемника, пропустите этот преемник

iii) если узел с той же позицией, что и преемник, находится в списке ЗАКРЫТО, котороеимеет меньшее значение f, чем у преемника, пропустите этот преемник, в противном случае добавьте узел в конец открытого списка (для цикла)

e) нажмите q в конце закрытого списка (в то время как цикл)

Спасибо

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...