본문 바로가기

알고리즘

A * 알고리즘

 

 길 찾기 알고리즘의 대표적인 예로 A * 알고리즘이 존재한다!

 

최단 경로로 시작점부터 목표지점까지 경로를 탐색하는 알고리즘으로서 매우 재미있고 유용한 알고리즘이다.

 

A* 알고리즘은 지난 블로그에 작성한 DFS, BFS 알고리즘의 활용버전이라고 생각하며 앞으로 공부해볼 다익스타라 알고리즘과 흡사한 유형이라고 생각할 수 있겠다.

 

A* 알고리즘

● A * 알고리즘 : 출발 꼭짓점에서부터 목표 꼭짓점까지 최단 경로를 탐색하는 휴라스틱기반의 그래프 탐색 알고리즘.

 

 

계산 방식

F(n) = g(n) + h(n)

 

- g(n) = 시작 노드부터 현재 노드까지의 비용

- h(n) = 현재 노드에서 목표 노드까지의 예상 비용

 

 보통 h(n)을 휴리스틱 함수라고 일컫는다. 

해당 휴리스틱 함수를 어떻게 지정하냐에 따라, 알고리즘 형태 결정

 

● 모든 경로를 다 찾지 않음 => 최단 경로 구하는 알고리즘에 적합

 따라서, 목적지에 얼마나 가까운 정점인지를 판단하는 피타고라스의 정의로 시작점부터 목적지까지 남은 거리를 직선적으로 혹은 노드를 지나쳐 걸리는 시간을 계산할 수 있음

 

 

고라니 TV의 A * 알고리즘 영상을 참고했다.

 

 

 

 열린리스트와 닫힌 리스트를 통해서 조건에 충족하는 근접 노드들을 방문하면서, 시작에서 도착지점까지의 이동경로를 계산하였을때, 최적의 길인 알고리즘을 구현할 수 있다.

 

 이론적으로 생각하는 것보다, 바로 실전에 응용하여 적용시켜보도록 하겠다.

 


 

C# 유니티 구현

 

void OpenListAdd(int checkX, int checkY)
{
    // 상하좌우 범위를 벗어나지 않고, 벽이 아니면서, 닫힌리스트에 없다면
    if (checkX >= bottomLeft.x && checkX < topRight.x + 1 && checkY >= bottomLeft.y && checkY < topRight.y + 1 && !NodeArray[checkX - bottomLeft.x, checkY - bottomLeft.y].isWall && !ClosedList.Contains(NodeArray[checkX - bottomLeft.x, checkY - bottomLeft.y]))
    {
        // 대각선 허용시, 벽 사이로 통과 안됨
        if (allowDiagonal) if (NodeArray[CurNode.x - bottomLeft.x, checkY - bottomLeft.y].isWall && NodeArray[checkX - bottomLeft.x, CurNode.y - bottomLeft.y].isWall) return;

        // 코너를 가로질러 가지 않을시, 이동 중에 수직수평 장애물이 있으면 안됨
        if (dontCrossCorner) if (NodeArray[CurNode.x - bottomLeft.x, checkY - bottomLeft.y].isWall || NodeArray[checkX - bottomLeft.x, CurNode.y - bottomLeft.y].isWall) return;

        
        // 이웃노드에 넣고, 직선은 10, 대각선은 14비용
        Node NeighborNode = NodeArray[checkX - bottomLeft.x, checkY - bottomLeft.y];
        int MoveCost = CurNode.G + (CurNode.x - checkX == 0 || CurNode.y - checkY == 0 ? 10 : 14);


        // 이동비용이 이웃노드G보다 작거나 또는 열린리스트에 이웃노드가 없다면 G, H, ParentNode를 설정 후 열린리스트에 추가
        if (MoveCost < NeighborNode.G || !OpenList.Contains(NeighborNode))
        {
            NeighborNode.G = MoveCost;
            NeighborNode.H = (Mathf.Abs(NeighborNode.x - TargetNode.x) + Mathf.Abs(NeighborNode.y - TargetNode.y)) * 10;
            NeighborNode.ParentNode = CurNode;

            OpenList.Add(NeighborNode);
        }
    }

 

 

 

'알고리즘' 카테고리의 다른 글

유니온 파인드  (0) 2024.04.01
다익스트라 알고리즘  (0) 2024.03.26
그리디  (0) 2024.03.24
해시  (0) 2024.03.22
투 포인터  (0) 2024.03.21