본문 바로가기

Algorithm/백준

[백준/JAVA] 🥈 1063번 킹

문제

8*8크기의 체스판에 왕이 하나 있다. 킹의 현재 위치가 주어진다. 체스판에서 말의 위치는 다음과 같이 주어진다. 알파벳 하나와 숫자 하나로 이루어져 있는데, 알파벳은 열을 상징하고, 숫자는 행을 상징한다. 열은 가장 왼쪽 열이 A이고, 가장 오른쪽 열이 H까지 이고, 행은 가장 아래가 1이고 가장 위가 8이다. 예를 들어, 왼쪽 아래 코너는 A1이고, 그 오른쪽 칸은 B1이다.

킹은 다음과 같이 움직일 수 있다.

  • R : 한 칸 오른쪽으로
  • L : 한 칸 왼쪽으로
  • B : 한 칸 아래로
  • T : 한 칸 위로
  • RT : 오른쪽 위 대각선으로
  • LT : 왼쪽 위 대각선으로
  • RB : 오른쪽 아래 대각선으로
  • LB : 왼쪽 아래 대각선으로

체스판에는 돌이 하나 있는데, 돌과 같은 곳으로 이동할 때는, 돌을 킹이 움직인 방향과 같은 방향으로 한 칸 이동시킨다. 아래 그림을 참고하자.

 

입력으로 킹이 어떻게 움직여야 하는지 주어진다. 입력으로 주어진 대로 움직여서 킹이나 돌이 체스판 밖으로 나갈 경우에는 그 이동은 건너 뛰고 다음 이동을 한다.

킹과 돌의 마지막 위치를 구하는 프로그램을 작성하시오.

입력

첫째 줄에 킹의 위치, 돌의 위치, 움직이는 횟수 N이 주어진다. 둘째 줄부터 N개의 줄에는 킹이 어떻게 움직여야 하는지 주어진다. N은 50보다 작거나 같은 자연수이고, 움직이는 정보는 위에 쓰여 있는 8가지 중 하나이다.

출력

첫째 줄에 킹의 마지막 위치, 둘째 줄에 돌의 마지막 위치를 출력한다.

예제 입출력

 

 

 

풀이

배열이 첫 행이 1이 아닌 8부터 시작하기 때문에 1로 시작하도록 바꿔주었다.

그리고 열 값인 A, B, C, ..., H를 아스키 코드 숫자 값으로 다뤄 king과 stone의 좌표 값을 int[열, 행]으로 갖게 만들었다.

 

king과 stone이 움직일 수 있는 8가지 명령어를 좌표를 통해 나타냈고,

enum 타입으로 만들어 R=0, L=1, B=2, ..., LB=7의 숫자 값에 매핑되게 만들어

R로 움직이라는 명령어가 들어왔을 때, enum에서 0값을 얻어 와, dx[0] dy[0] 값을 참조해 (1, 0)방향으로 킹 혹은 돌을 움직인다.

static int[] dx = {1, -1, 0, 0, 1, -1, 1, -1};
static int[] dy = {0, 0, -1, 1, 1, 1, -1, -1};
public enum Move {
    R, L, B, T, RT, LT, RB, LB;
}

 

 

*주요 로직

if(king이 이동할 위치가 체스판 밖이면 continue;)

else

    if(king이 이동할 위치에 stone이 있으면)

          stone을 같은 방향으로 먼저 이동시키기 (이때, stone이 이동할 위치가 체스판 밖이면 continue;)

          king을 이동시키기

    else //stone이 없으면

          king만 이동시키기

 

 

 

TestCase 4번에 대해 검증하기

 

king 처음 위치 : A1 -> (65, 1)

stone 처음 위치 : A2 -> (65, 2)

 

T 이동

king(65, 1) -> T(0, +1) -> king(65, 2) : king이 이동하려는 위치에 stone 존재

stone(65, 2) -> T(0, +1) -> stone(65, 3) : stone을 같은 방향으로 먼저 이동(체스판 내 범위이기 때문에 이동 가능)

king(65, 2) : king을 이동

 

R 이동

king(65, 2) -> R(+1, 0) -> king(66, 2) : king이 이동하려는 위치에 stone이 존재하지 않기 때문에 king만 이동

 

결과출력

king(66, 2) -> 변환 -> B2

stone(65, 3) -> 변환 -> A3

 

 

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class ex1063_킹 {
    static int[] dx = {1, -1, 0, 0, 1, -1, 1, -1};
    static int[] dy = {0, 0, -1, 1, 1, 1, -1, -1};

    //ordinal() : 원소에 열거된 순서를 정수 값으로 리턴
    public enum Move {
        R, L, B, T, RT, LT, RB, LB;
    }
    static int n;

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;

        st = new StringTokenizer(br.readLine());
        int[] king = new int[2];
        int[] stone = new int[2];

//        킹의 초기 위치 세팅
        String kingXY = st.nextToken();
        initObjectXY(kingXY, king);
//        돌의 초기 위치 세팅
        String stoneXY = st.nextToken();
        initObjectXY(stoneXY, stone);

        n = Integer.parseInt(st.nextToken());
        for (int i = 0; i < n; i++) {
            String func = br.readLine();
//            System.out.println("func : " + func);
//            움직임 정보의 인덱스 값 받아오기 ex) func="B"이면 2
            int index = Move.valueOf(func).ordinal();
//            System.out.println("index : " + index);
//            System.out.println("Move에서 가져온 이동 정보 : " + dx[index] + ", " + dy[index]);
//            king의 다음 위치
            int kingNX = king[0] + dx[index];
            int kingNY = king[1] + dy[index];
//            System.out.println("king의 다음 위치 : " + kingNX + kingNY);
//             king의 다음 위치가 체스판 밖이면 움직이지 않음
//            king은 문자(아스키코드)로 처리하기 때문에 숫자값 적절하게 설정
            if(kingNX<65 || kingNX>72 || kingNY<1 || kingNY>8) continue;

//            king의 다음 위치에 stone이 있는 경우
//            stone먼저 이동 후 king 이동(이때 stone 범위 체크, stone은 범위 내에 존재하기 때문에 king 범위는 체크 안해도 무방)
            if(kingNX==stone[0] && kingNY==stone[1]){
//                System.out.println("이동 중에 돌이 있음");
//                System.out.println("stone 이동 후 king 이동");
                int stoneNX = stone[0] + dx[index];
                int stoneNY = stone[1] + dy[index];
//                stone 다음 위치가 체스판 밖이면 움직이지 않음
                if(stoneNX<65 || stoneNX>72 || stoneNY<1 || stoneNY>8) continue;
                else{
                    stone[0] = stoneNX;
                    stone[1] = stoneNY;
                    king[0] = kingNX;
                    king[1] = kingNY;
                }
            }
            else{
//            king의 다음 위치에 stone이 없는 경우, king만 이동
//                System.out.println("king만 이동");
                king[0] = kingNX;
                king[1] = kingNY;
            }
        }
        System.out.println(makeAnswer(king));
        System.out.println(makeAnswer(stone));
    }

    static void initObjectXY(String strXY, int[] object){
        object[0] = strXY.charAt(0); //int형이기 때문에 A -> 65 이런식으로 대입됨
        object[1] = Character.getNumericValue(strXY.charAt(1));
    }
    static StringBuilder makeAnswer(int[] object){
        StringBuilder answer = new StringBuilder();
        answer.append((char)object[0]);
        answer.append(object[1]);
        return answer;
    }
}