본문 바로가기

코딩 테스트/PROGRAMMERS

[Java] Lv.2 리코쳇 로봇

문제

문제 설명
리코쳇 로봇이라는 보드게임이 있습니다.

이 보드게임은 격자모양 게임판 위에서 말을 움직이는 게임으로,
시작 위치에서 목표 위치까지 최소 몇 번만에 도달할 수 있는지 말하는 게임입니다.

이 게임에서 말의 움직임은 상, 하, 좌, 우 4방향 중 하나를 선택해서
게임판 위의 장애물이나 맨 끝에 부딪힐 때까지 미끄러져 이동하는 것을 한 번의 이동으로 칩니다.

다음은 보드게임판을 나타낸 예시입니다.

...D..R
.D.G...
....D.D
D....D.
..D....
여기서 "."은 빈 공간을, "R"은 로봇의 처음 위치를, "D"는 장애물의 위치를, "G"는 목표지점을 나타냅니다.
위 예시에서는 "R" 위치에서 아래, 왼쪽, 위, 왼쪽, 아래, 오른쪽, 위 순서로 움직이면 
7번 만에 "G" 위치에 멈춰 설 수 있으며, 이것이 최소 움직임 중 하나입니다.

게임판의 상태를 나타내는 문자열 배열 board가 주어졌을 때, 
말이 목표위치에 도달하는데 최소 몇 번 이동해야 하는지 return 하는 solution함수를 완성하세요. 
만약 목표위치에 도달할 수 없다면 -1을 return 해주세요.

제한 사항
3 ≤ board의 길이 ≤ 100
3 ≤ board의 원소의 길이 ≤ 100
board의 원소의 길이는 모두 동일합니다.

문자열은 ".", "D", "R", "G"로만 구성되어 있으며
각각 빈 공간, 장애물, 로봇의 처음 위치, 목표 지점을 나타냅니다.

"R"과 "G"는 한 번씩 등장합니다.
 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

문제 풀이

아래 블로그 글을 참고하여 풀이 했다.

시작점을 찾아서 해당 위치부터 큐에 넣고 네 방향으로 D 혹은 맵의 맨끝에 도달할 때까지 확인한다.

장애물에 부딫히거나 맨끝에 도달할 경우 해당 위치를 다시 시작점으로 큐에 넣고 횟수를 +1 하는 방식으로 계속 진행한다.

G 지점에 도달했을 때 이전에 도달했었던 이동 횟수와 비교하여 더 작은 숫자를 다시 기록한다.

 

[프로그래머스] 리코쳇 로봇 - Java(자바)

문제 이해리코쳇 로봇이라는 보드게임이 있습니다.게임판에는 "." - 빈공간, "R" - 로봇, "D" - 장애물, "G" - 목표지점 으로 구성되어있고 "R", "G는 무조건 하나씩 존재합니다.로봇이 목표지점으로 갈

ansdyd23.tistory.com

 

자바 코드

import java.util.*;
class Solution {
    public int solution(String[] board) {
        int answer = Integer.MAX_VALUE;
        // 방문 처리를 위한 배열
        boolean[][] visit = new boolean[board.length][board[0].length()];
        
        // 현재 위치를 저장할 큐
        Queue<int[]> que = new LinkedList<>();
        
        for(int i = 0; i < board.length; i++){
            for(int j = 0; j < board[i].length(); j++){
                // 시작점을 찾으면 해당 위치를 큐에 삽입하고 방문처리
                if(board[i].charAt(j) == 'R') {
                    que.add(new int[] {i, j, 0});
                    visit[i][j] = true;
                    
                    // 큐가 빌때까지 반복
                    while(!que.isEmpty()){
                        int[] tmp = que.poll();
                        
                        // 뽑은 현재 위치가 도착지점이면 현재의 답과 비교하여 작은 쪽을 저장
                        if(board[tmp[0]].charAt(tmp[1]) == 'G') {
                            answer = Math.min(answer, tmp[2]);
                        }
                        
                        // 네 방향으로 탐색
                        for(int k = 0; k < 4; k++){
                            // 상 하 좌 우, x, y, 이동 횟수, 보드게임판
                            // 상하좌우 값을 확인하여 한 방향을 확인하고 멈춘 위치를 반환한다.
                            int[] XY = move(k, tmp[0] , tmp[1], tmp[2], board);
                            int x = XY[0];
                            int y = XY[1];
                            
                            // 부딫힌 위치가 방문하지 않은 위치일 경우
                            // 해당 위치를 현재 위치로 저장하고 방문처리
                            if(!visit[x][y]){
                                que.add(XY);
                                visit[x][y] = true;
                            }
                        }
                    }
                }
            }
        }
        
        return answer == Integer.MAX_VALUE ? -1 : answer;
    }
    
    // 상하좌우 장애물이나 맨 끝에 부딪힐때까지 미끄러지기
    public int[] move(int k, int x, int y, int cnt, String[] board){
        int[] result = new int[3];
        
        // 상
        if(k == 0){
            // 현재 x위치부터 맨 위 0까지 확인
            for(int i = x; i >= 0; i--){
                // 현재 i줄의 y 좌표가 D, 즉 벽일 경우 해당 위치를 반환한다.
                if(board[i].charAt(y) == 'D'){
                    return new int[]{i + 1, y, cnt + 1};
                }
            }
            
            // 위의 반복문에 걸리지 않았을 경우 보드판 y열의 맨 위 끝에 붙은 것이다.
            result[0] = 0;
            result[1] = y;
            result[2] = cnt + 1;
        }else if(k == 1){ // 하
            // 현재 x위치부터 맨 아래 board.length -1 까지 확인
            for(int i = x; i < board.length; i++){
                // 현재 i줄의 y 좌표가 D, 즉 벽일 경우 해당 위치를 반환한다.
                if(board[i].charAt(y) == 'D'){
                    return new int[]{i - 1, y, cnt + 1};
                }
            }            
            
            // 위의 반복문에 걸리지 않았을 경우 보드판 y열의 맨 아래 끝에 붙은 것이다.
            result[0] = board.length - 1;
            result[1] = y;
            result[2] = cnt + 1;
        }else if(k == 2){ // 우
            // 현재 y위치부터 맨 오른쪽 board.length -1 까지 확인
            for(int i = y; i < board[0].length(); i++){
                // 현재 i줄의 x 좌표가 D, 즉 벽일 경우 해당 위치를 반환한다.
                if(board[x].charAt(i) == 'D'){
                    return new int[]{x, i - 1, cnt + 1};
                }
            }            
            
            // 위의 반복문에 걸리지 않았을 경우 보드판 x행의 맨 오른쪽 끝에 붙은 것이다.
            result[0] = x;
            result[1] = board[0].length() - 1;
            result[2] = cnt + 1;
        }else if(k == 3){
            // 현재 y위치부터 맨 왼쪽 0 까지 확인
            for(int i = y; i >= 0; i--){
                // 현재 i줄의 x 좌표가 D, 즉 벽일 경우 해당 위치를 반환한다.
                if(board[x].charAt(i) == 'D'){
                    return new int[]{x, i + 1, cnt + 1};
                }
            }            
            
            // 위의 반복문에 걸리지 않았을 경우 보드판 x행의 맨 왼쪽 끝에 붙은 것이다.
            result[0] = x;
            result[1] = 0;
            result[2] = cnt + 1;
        }
        
        // 장애물에 걸리지 않고 벽에 부딫힌 위치를 반환
        return result;
    }
}

 

'코딩 테스트 > PROGRAMMERS' 카테고리의 다른 글

[Java] Lv.2 택배 배달과 수거하기  (0) 2024.06.11
[Java] Lv2 시소 짝꿍  (2) 2024.06.11
[Java] Lv.2 미로 탈출  (2) 2024.06.06
[Java] Lv.2 혼자서 하는 틱택토  (0) 2024.06.04
[Java] Lv.2 당구 연습  (0) 2024.06.04