D+45 BFS 게임맵 최단거리

초록귤·2025년 2월 8일
1

100일프로젝트

목록 보기
37/42
post-thumbnail

문제

ROR 게임은 두 팀으로 나누어서 진행하며, 상대 팀 진영을 먼저 파괴하면 이기는 게임입니다. 따라서, 각 팀은 상대 팀 진영에 최대한 빨리 도착하는 것이 유리합니다.

지금부터 당신은 한 팀의 팀원이 되어 게임을 진행하려고 합니다. 다음은 5 x 5 크기의 맵에, 당신의 캐릭터가 (행: 1, 열: 1) 위치에 있고, 상대 팀 진영은 (행: 5, 열: 5) 위치에 있는 경우의 예시입니다.

위 그림에서 검은색 부분은 벽으로 막혀있어 갈 수 없는 길이며, 흰색 부분은 갈 수 있는 길입니다. 캐릭터가 움직일 때는 동, 서, 남, 북 방향으로 한 칸씩 이동하며, 게임 맵을 벗어난 길은 갈 수 없습니다.
아래 예시는 캐릭터가 상대 팀 진영으로 가는 두 가지 방법을 나타내고 있습니다.

첫 번째 방법은 11개의 칸을 지나서 상대 팀 진영에 도착했습니다.

두 번째 방법은 15개의 칸을 지나서 상대팀 진영에 도착했습니다.

위 예시에서는 첫 번째 방법보다 더 빠르게 상대팀 진영에 도착하는 방법은 없으므로, 이 방법이 상대 팀 진영으로 가는 가장 빠른 방법입니다.

만약, 상대 팀이 자신의 팀 진영 주위에 벽을 세워두었다면 상대 팀 진영에 도착하지 못할 수도 있습니다. 예를 들어, 다음과 같은 경우에 당신의 캐릭터는 상대 팀 진영에 도착할 수 없습니다.

게임 맵의 상태 maps가 매개변수로 주어질 때, 캐릭터가 상대 팀 진영에 도착하기 위해서 지나가야 하는 칸의 개수의 최솟값을 return 하도록 solution 함수를 완성해주세요. 단, 상대 팀 진영에 도착할 수 없을 때는 -1을 return 해주세요.

제한사항
maps는 n x m 크기의 게임 맵의 상태가 들어있는 2차원 배열로, n과 m은 각각 1 이상 100 이하의 자연수입니다.
n과 m은 서로 같을 수도, 다를 수도 있지만, n과 m이 모두 1인 경우는 입력으로 주어지지 않습니다.
maps는 0과 1로만 이루어져 있으며, 0은 벽이 있는 자리, 1은 벽이 없는 자리를 나타냅니다.
처음에 캐릭터는 게임 맵의 좌측 상단인 (1, 1) 위치에 있으며, 상대방 진영은 게임 맵의 우측 하단인 (n, m) 위치에 있습니다.

풀이

function solution(maps) {
    const n = maps.length;        // 행의 수
    const m = maps[0].length;     // 열의 수
    const directions = [[1, 0], [-1, 0], [0, 1], [0, -1]]; // 남, 북, 동, 서 방향
    const queue = [[0, 0, 1]];    // [행, 열, 거리]
    const visited = Array.from({ length: n }, () => Array(m).fill(false)); // 방문 여부 초기화
    visited[0][0] = true;          // 시작점 방문 처리

    while (queue.length) {
        const [x, y, distance] = queue.shift(); // 큐에서 현재 위치와 거리 꺼내기

        // 도착점에 도착했을 때
        if (x === n - 1 && y === m - 1) {
            return distance; // 거리 반환
        }

        // 네 방향으로 이동
        for (const [dx, dy] of directions) {
            const nx = x + dx; // 새로운 행
            const ny = y + dy; // 새로운 열

            // 맵 범위와 벽 체크
            if (nx >= 0 && nx < n && ny >= 0 && ny < m && maps[nx][ny] === 1 && !visited[nx][ny]) {
                visited[nx][ny] = true; // 방문 처리
                queue.push([nx, ny, distance + 1]); // 큐에 추가
            }
        }
    }

    return -1; // 도착할 수 없는 경우
}

기억할 것

갈 수 있는 동서남북 directions 배열 지정
while(queue.length)로 자바스크립트는 while 문 조건에서 0인지 아닌지 체크해서 음수도 반복문 돌아가기 때문에 주의할 것.
shift사용으로 최단거리를 구할 수 있게 된다!

Array.from()
Array.from() 정적 메서드는 순회 가능 또는 유사배열 객체에서 얕게 복사된 새로운 Array 인스턴스를 생성한다.

Array.from(array, mapFn, thisArg) 매개변수

  1. array : 배열로 변환할 순회 가능 또는 유사 배열 객체
  2. mapFn(optional) : 배열의 모든 요소에 대해 호출할 함수,
    이 함수를 제공하면 배열에 추가할 모든 값이 이 함수를 통해 먼저 전달되고, mapFn의 반환 값이 대신 배열에 추가됩니다. 이 함수는 다음 인수를 사용하여 호출됩니다.
  • element : 배열에서 처리 중인 현재 요소
  • index : 배열에서 처 리 중인 현재 요소의 인덱스
  1. thisArg(optional) : mapFn실행 시에 this로 사용할 값.
    다음과 같은 경우에 Array.from()을 사용하면 Array를 만들 수 있습니다.
    순회 가능 객체(Map, Set과 같은 객체)인 경우. 또는 객체가 순회 가능이 아니라면,
    유사 배열 객체(length 속성과 인덱싱된 요소가 있는 객체).
    순회 가능이 아니거나 유사 배열이 아닌 일반 객체를 배열로 변환하려면
    (속성 키, 값 또는 둘을 모두 열거하여) Object.keys(), Object.values(), 또는 Object.entries()를 사용해야 합니다.
    비동기 순회 가능을 배열로 변환하려면 Array.fromAsync()를 사용합니다.
    Array.from(obj, mapFn, thisArg)는 중간 배열을 생성하지 않는다는 점과 배열이 아직 생성 중이기 때문에 전체 배열 없이 두 개의 인수(element, index)만 받는다는 점을 제외하면 Array.from(obj).map(mapFn, thisArg)과 동일한 결과를 가져옵니다.
profile
초록색 귤이 노랑색으로 익어가듯, 실력이 익어가기 위해 노력하는 개발자 lahee입니다.

0개의 댓글

관련 채용 정보