8*8크기의 체스판에 왕이 하나 있다. 킹의 현재 위치가 주어진다. 체스판에서 말의 위치는 다음과 같이 주어진다. 알파벳 하나와 숫자 하나로 이루어져 있는데, 알파벳은 열을 상징하고, 숫자는 행을 상징한다. 열은 가장 왼쪽 열이 A이고, 가장 오른쪽 열이 H까지 이고, 행은 가장 아래가 1이고 가장 위가 8이다. 예를 들어, 왼쪽 아래 코너는 A1이고, 그 오른쪽 칸은 B1이다.
킹은 다음과 같이 움직일 수 있다.
R : 한 칸 오른쪽으로
L : 한 칸 왼쪽으로
B : 한 칸 아래로
T : 한 칸 위로
RT : 오른쪽 위 대각선으로
LT : 왼쪽 위 대각선으로
RB : 오른쪽 아래 대각선으로
LB : 왼쪽 아래 대각선으로
체스판에는 돌이 하나 있는데, 돌과 같은 곳으로 이동할 때는, 돌을 킹이 움직인 방향과 같은 방향으로 한 칸 이동시킨다. 아래 그림을 참고하자.
입력으로 킹이 어떻게 움직여야 하는지 주어진다. 입력으로 주어진 대로 움직여서 킹이나 돌이 체스판 밖으로 나갈 경우에는 그 이동은 건너 뛰고 다음 이동을 한다.
킹과 돌의 마지막 위치를 구하는 프로그램을 작성하시오.
import java.io.*;
import java.util.StringTokenizer;
public class Baekjoon1063 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
char[][] chessBoard = new char[8][8];
String command;
String input = br.readLine();
StringTokenizer st = new StringTokenizer(input);
String kingPosition = st.nextToken();
String stonePosition = st.nextToken();
int test = Integer.parseInt(st.nextToken());
int[] kingPositionArray = {8 - Character.getNumericValue(kingPosition.charAt(1)), getIndex(kingPosition)};
int[] stonePositionArray = {8 - Character.getNumericValue(stonePosition.charAt(1)), getIndex(stonePosition)};
for (int i = 0; i < test; i++) {
command = br.readLine();
if (command.length() == 2) {
checkTwoCommand(command, kingPositionArray, stonePositionArray);
continue;
}
checkOneCommand(command.charAt(0), kingPositionArray, stonePositionArray);
}
bw.write(makeString(kingPositionArray));
bw.newLine();
bw.write(makeString(stonePositionArray));
bw.newLine();
bw.flush();
bw.close();
}
public static void checkTwoCommand(String command, int[] king, int[] stone) {
switch (command) {
case "LT":
if (king[0] > 0 && king[1] > 0) { // 무조건 만족시켜야 하는 조건
if (king[0] - 1 == stone[0] && king[1] - 1 == stone[1]) { // LT 위치에 돌이 있을 때
if (stone[0] > 0 && stone[1] > 0) {
king[0] -= 1;
king[1] -= 1;
stone[0] -= 1;
stone[1] -= 1;
return;
}
return;
}
king[0] -= 1;
king[1] -= 1;
return;
}
return;
case "RT":
if (king[0] > 0 && king[1] < 7) {
if (king[0] - 1 == stone[0] && king[1] + 1 == stone[1]) {
if (stone[0] > 0 && stone[1] < 7) {
king[0] -= 1;
king[1] += 1;
stone[0] -= 1;
stone[1] += 1;
return;
}
return;
}
king[0] -= 1;
king[1] += 1;
return;
}
return;
case "RB":
if (king[0] < 7 && king[1] < 7) {
if (king[0] + 1 == stone[0] && king[1] + 1 == stone[1]) {
if (stone[0] < 7 && stone[1] < 7) {
king[0] += 1;
king[1] += 1;
stone[0] += 1;
stone[1] += 1;
return;
}
return;
}
king[0] += 1;
king[1] += 1;
return;
}
return;
case "LB":
if (king[0] < 7 && king[1] > 0) {
if (king[0] + 1 == stone[0] && king[1] - 1 == stone[1]) {
if (stone[0] < 7 && stone[1] > 0) {
king[0] += 1;
king[1] -= 1;
stone[0] += 1;
stone[1] -= 1;
return;
}
return;
}
king[0] += 1;
king[1] -= 1;
}
}
}
public static void checkOneCommand(char command, int[] king, int[] stone) {
switch (command) {
case 'L':
if (king[1] == 0) { // 0열에 있을 때 움직일 수 없음
return;
}
if (king[0] == stone[0] && king[1] - 1 == stone[1]) { // 돌을 밀고 움직여야 할 때
if (stone[1] > 0) {
king[1] -= 1;
stone[1] -= 1;
return;
}
return;
}
king[1] -= 1;
return;
case 'T':
if (king[0] == 0) {
return;
}
if (king[0] - 1 == stone[0] && king[1] == stone[1]) {
if (stone[0] > 0) {
king[0] -= 1;
stone[0] -= 1;
return;
}
return;
}
king[0] -= 1;
return;
case 'R':
if (king[1] == 7) {
return;
}
if (king[0] == stone[0] && king[1] + 1 == stone[1]) {
if (stone[1] < 7) {
king[1] += 1;
stone[1] += 1;
return;
}
return;
}
king[1] += 1;
return;
case 'B':
if (king[0] == 7) {
return;
}
if (king[0] + 1 == stone[0] && king[1] == stone[1]) {
if (stone[0] < 7) {
king[0] += 1;
stone[0] += 1;
return;
}
return;
}
king[0] += 1;
}
}
public static int getIndex(String position) {
char ch = position.charAt(0);
switch (ch) {
case 'A':
return 0;
case 'B':
return 1;
case 'C':
return 2;
case 'D':
return 3;
case 'E':
return 4;
case 'F':
return 5;
case 'G':
return 6;
case 'H':
return 7;
}
return -1;
}
public static String makeString(int[] positionArray) {
StringBuilder sb = new StringBuilder();
if(positionArray[1]==0) {
sb.append("A");
}
if(positionArray[1]==1) {
sb.append("B");
}
if(positionArray[1]==2) {
sb.append("C");
}
if(positionArray[1]==3) {
sb.append("D");
}
if(positionArray[1]==4) {
sb.append("E");
}
if(positionArray[1]==5) {
sb.append("F");
}
if(positionArray[1]==6) {
sb.append("G");
}
if(positionArray[1]==7) {
sb.append("H");
}
int number = 8-positionArray[0];
sb.append(Integer.toString(number));
return sb.toString();
}
}
킹이 움직일 수 있는 위치는 총 8가지가 있는데, 이들을 두 가지로 구분했다. 입력받은 command의 길이를 체크해서 길이가 1일 경우 checkOneCommand 메서드를 통해 R(우), L(좌), B(하), T(상)를 판단하고 길이가 2인 경우 checkTwoCommand 메서드로 RT(우상), LT(좌상), RB(우하), LB(좌하)를 판단했다.
킹은 입력된 방향으로 움직이기 전에 움직일 수 있는 위치인지 확인하고, 진행 방향에 돌이 있는지를 확인한다. 움직일 수 없는 위치란 예를 들어 킹이 현재 체스 보드의 맨 왼쪽 칸에 있는데 입력값으로 L이 들어온 경우가 있다. 킹은 체스 보드를 뚫고 왼쪽으로 움직일 수는 없기 때문에 이는 움직일 수 없는 위치가 되는 것이다. 그 다음으로는 킹의 진행 경로 상 돌의 유무를 판단한다. 돌이 없는 경우엔 킹의 위치만 움직이면 그만이지만, 돌이 있는 경우에는 돌 역시 상기한 것 처럼 움직일 수 있는 위치인지를 확인해야 한다. 그래서 움직일 수 있는 위치이면 돌을 한 칸 밀고 킹이 기존 돌의 위치에 놓이게 되는 것이다.
사실 굉장히 무식하게(?) 단순하게 접근하고 코드를 짰다. 일일이 방향을 확인하고 상태를 확인한 뒤 옮겨줬기 때문이다. 이렇게 문제를 푸니 로직을 생각하는 시간은 짧아졌지만, 코드가 굉장히 복잡하고 오히려 내가 코드를 쓰다가 헷갈리는 등 여러 문제가 발생했다... 만약 다시 이런 문제를 마주하게 된다면 그때는 좀 더 짜임새 있는 코드를 짜봐야겠다.
역시 GOAT