Алгоритм A-star приводит к странным, медленным и неэффективным выборам - PullRequest
1 голос
/ 31 марта 2020

Сегодня я попытался создать алгоритм поиска пути A-STAR с визуализацией в PyGame. Код:

import pygame, time

pygame.init()
pygame.font.init()
#----------[0,1,2]
#GRID[x][y][g/h/f]
#g_cost: distance from starting to current node
#h_cost: distance from ending to current node
#f_cost: sum of previous two costs. That way, the lower
#the f cost, the more likely a node is to be on the path

WIDTH = 20
HEIGHT = 15
XSTART = 5
YSTART = 5
XEND = 15
YEND = 10
TICK = 10000000
CLOCK = pygame.time.Clock()
OPEN_NODES = []
CLOSED_NODES = []
BEACON = 0
SQUARE = 50
GEN = 0
WHITE = (255,255,255)

GRID = []

#func to find distance between 2 nodes
def find_dist(coor1,coor2):
    x1,y1 = coor1
    x2,y2 = coor2
    x_diff = abs(x1-x2)
    y_diff = abs(y1-y2)
    smaller = min([x_diff,y_diff])
    #diagonal multiplied by sqrt(2) approximately
    dist = round(smaller*1.4+(max([x_diff,y_diff])-smaller))*10
    return dist

#super stupid way to get all node neighbors
def get_neighbors(coors):
    x,y = coors
    neighbors = []
    if x-1 > -1:
        neighbors.append(GRID[x-1][y])
    if x-1 > -1 and y+1 < HEIGHT:   
        neighbors.append(GRID[x-1][y+1])
    if y+1 < HEIGHT:
        neighbors.append(GRID[x][y+1])
    if y+1 < HEIGHT and x+1 < WIDTH:
        neighbors.append(GRID[x+1][y+1])
    if x+1 < WIDTH:
        neighbors.append(GRID[x+1][y])
    if x+1 < WIDTH and y-1 > -1:
        neighbors.append(GRID[x+1][y-1])
    if y-1 > -1:
        neighbors.append(GRID[x][y-1])
    if y-1 > -1 and x-1 > -1:
        neighbors.append(GRID[x-1][y-1])
    return neighbors

#returns list without duplicates
def elim_duplicates(listin):
    for element in listin:
        if listin.count(element) > 1:
            listin.pop(listin.index(element))
    return listin


#creates main grid
for x in range(WIDTH):
    COLUMN = []
    for y in range(HEIGHT):
        COLUMN.append([-1,-1])
    GRID.append(COLUMN)
GRID[XSTART][YSTART] = [-2,-2]
GRID[XEND][YEND] = [-3,-3]

#adds costs to each node
for x in range(WIDTH):
    for y in range(HEIGHT):
        g_cost = find_dist([x,y],[XSTART,YSTART])
        h_cost = find_dist([x,y],[XEND,YEND])
        f_cost = g_cost + h_cost
        GRID[x][y] = [g_cost,h_cost,f_cost,x,y]

#adds the starting node to open nodes,
#which is a list containing all nodes
#that will be checked for the lowest f cost
OPEN_NODES.append(GRID[XSTART][YSTART])

WINDOW = pygame.display.set_mode((WIDTH*SQUARE, HEIGHT*SQUARE))
pygame.display.set_caption('A* Algorithm')

RUN = True

PATH_NODES = []

while RUN:
    GEN += 1
    CLOCK.tick(TICK)
    #cycle control
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            RUN = False
    #updates costs
    for x in range(WIDTH):
        for y in range(HEIGHT):
            g_cost = find_dist([x,y],[XSTART,YSTART])
            h_cost = find_dist([x,y],[XEND,YEND])
            f_cost = g_cost + h_cost
            GRID[x][y] = [g_cost,h_cost,f_cost,x,y]
    #creates a list with only f costs
    f_cost_list = []
    for i in OPEN_NODES:
        f_cost_list.append(i[2])
    #finds the node with the lowest f cost
    CURRENT_NODE = OPEN_NODES[f_cost_list.index(min(f_cost_list))]
    #adds all neighbors of the current node and removes duplicates
    OPEN_NODES.extend(get_neighbors(CURRENT_NODE[3:]))
    OPEN_NODES = elim_duplicates(OPEN_NODES)
    #adds current node to possible path nodes
    PATH_NODES.append(CURRENT_NODE)
    #removes current node from open nodes
    OPEN_NODES.remove(CURRENT_NODE)
    #removes all possible duplicates from lists
    PATH_NODES = elim_duplicates(PATH_NODES)
    OPEN_NODES = elim_duplicates(OPEN_NODES)
    #checks if path has been found
    if CURRENT_NODE[3] == XEND and CURRENT_NODE[4] == YEND:
        pygame.draw.rect(WINDOW,(0,255,255), (490, 490, SQUARE, SQUARE))
        print('DONE')
        time.sleep(3)
        pygame.quit()
    #draws all open nodes
    for i in OPEN_NODES:
        pygame.draw.rect(WINDOW,(0,0,255),(i[3]*SQUARE,i[4]*SQUARE,SQUARE,SQUARE))
    #draws all possible path nodes
    for i in PATH_NODES:
        pygame.draw.rect(WINDOW,(255,0,0),(i[3]*SQUARE,i[4]*SQUARE,SQUARE,SQUARE))
    #draws start and end nodes
    pygame.draw.rect(WINDOW,(0,255,0), (XSTART*SQUARE, YSTART*SQUARE, SQUARE, SQUARE))
    pygame.draw.rect(WINDOW,(0,255,0), (XEND*SQUARE,YEND*SQUARE,SQUARE,SQUARE))
    #shows generation
    font = pygame.font.Font(None, 100)
    text = font.render(str(GEN), 1, WHITE)
    WINDOW.blit(text, (10,10))
    #updates screen
    pygame.display.update()
    WINDOW.fill((0, 0, 0))
pygame.quit()

Всякий раз, когда я запускаю алгоритм с начальной и конечной координатами, как показано, это странный результат, который показывает:

astar result

Он еще не показывает точный путь, но ошибки в алгоритме хорошо видны: дыры, странные ребра и т. Д. c.

Что может быть причиной этого?

...