[SWEA 1873] 상호의 배틀필드

업데이트:

문제

  • SWEA 1873번
  • 문제의 저작권은 SW Expert Academy에 있습니다.

접근방식

나는 처음에 명령어가 하나씩 입력될때 마다 맵에 ‘^’, ‘v’, ‘<’, ‘>’ 의 방향을 계속 바꿔주어야 한다고 생각했다.
그래서 처음에 명령어가 1. 방향인 경우, 2. 포탄인 케이스 둘다 맵에 방향을 적용하려고 하니 코드가 복잡해지고 로직을 어떻게 구현해야 할지 막막했다. 그러나 깨달은 것은 게임이 진행되는 동안에는 탱크의 방향만 알면 되지 맵에 적어줄 필요가 없다는 것이다. 이를 생각하니 코드를 짜기가 한결 수월해졌다.

  • 처음에 map에 좌표값을 입력 받을 때
    입력된 값이 방향(‘^’, ‘v’, ‘<’, ‘>’)을 나타내는 경우, 현재 좌표의 값을 평지’.’로 변경해주고 탱크방향을 결정한다.

  • 1.명령이 포탄인 경우
    계속 직진을 하다가(while문) 다음 좌표가 무엇인지에 따라 멈추는 조건을 걸어주면 된다.
    다음 좌표가 범위를 벗어나거나 강철인 경우 중단(break)하고, 다음 좌표가 벽돌인 경우에는 다음 좌표값을 평지’.’로 만들어주고 중단(break)한다.

  • 2.명령이 방향인 경우
    게임이 시작되면 탱크는 평지인 곳만 지나가기 때문에 이동 할때마다 현재 좌표를 평지로 바꿔줄 필요가 없다.(문제를 잘 읽자!!!)
    입력된 방향에 따라서 탱크방향을 결정해 준 후, 다음 좌표값을 구해준다. 그리고 다음 좌표값이 범위를 벗어나지 않고 평지인 경우에 현재 좌표를 다음 좌표값으로 변경해주면 된다. 이외의 경우는 직진할 수 없기 때문에 아까 결정한 탱크방향만 가지고 있으면 되므로 아무 작업도 수행하지 않는다.

  • 출력 할 때 여기서 출력할때만 현재 탱크 방향에 따라 ‘^’, ‘v’, ‘<’, ‘>’을 정해주고 맵에 적용시키면 된다.

코드

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

public class Swea_1873_Test {

	static int T;
	static int H, W;
	static char[][] map;
	static StringTokenizer st;
	static int[][] dirArr = { { -1, 0 }, { 1, 0 }, { 0, -1 }, { 0, 1 } };
	static String input;
	static int inputCnt;

	public static void main(String[] args) throws IOException {

		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

		T = Integer.parseInt(br.readLine());
		for (int tc = 1; tc <= T; tc++) {

			st = new StringTokenizer(br.readLine(), " ");
			H = Integer.parseInt(st.nextToken());
			W = Integer.parseInt(st.nextToken());

			int x = 0, y = 0, dir = 0; // 출발 좌표 x, y, 현재 방향
			map = new char[H][W];

			for (int i = 0; i < H; i++) {
				String s = br.readLine();
				for (int j = 0; j < W; j++) {
					map[i][j] = s.charAt(j);
					switch (map[i][j]) {
					case '^':
						map[i][j] = '.';
						x = i;
						y = j;
						dir = 0;
						break;

					case 'v':
						map[i][j] = '.';
						x = i;
						y = j;
						dir = 1;
						break;

					case '<':
						map[i][j] = '.';
						x = i;
						y = j;
						dir = 2;
						break;

					case '>':
						map[i][j] = '.';
						x = i;
						y = j;
						dir = 3;
						break;
					}
				}
			}

			inputCnt = Integer.parseInt(br.readLine());
			input = br.readLine();

			// 게임 시작
			for (int i = 0; i < inputCnt; i++) {
				if (input.charAt(i) == 'S') { // 1. 입력이 포탄이면
					int nx = x;
					int ny = y;
					// 계속 직진하다가
					while (true) {
						nx += dirArr[dir][0];
						ny += dirArr[dir][1];

						// 다음 좌표가 범위를 벗어나거나 강철벽이면
						if (nx < 0 || nx >= H || ny < 0 || ny >= W || map[nx][ny] == '#')
							break;

						// 다음 좌표가 벽돌이면
						if (map[nx][ny] == '*') {
							map[nx][ny] = '.';
							break;
						}
					}
				} else { // 2. 입력이 방향이면
					switch (input.charAt(i)) {
					case 'U':
						dir = 0;
						break;

					case 'D':
						dir = 1;
						break;

					case 'L':
						dir = 2;
						break;

					case 'R':
						dir = 3;
						break;
					}

					int nx = x + dirArr[dir][0];
					int ny = y + dirArr[dir][1];
					// 다음 좌표가 범위 안이고 평지이면 이동
					if (nx >= 0 && nx < H && ny >= 0 && ny < W && map[nx][ny] == '.') {
						x = nx;
						y = ny;
					}
				}
			} // 게임 끝

			// 현재 방향위치 맵에 넣어주기
			switch (dir) {
			case 0:
				map[x][y] = '^';
				break;

			case 1:
				map[x][y] = 'v';
				break;

			case 2:
				map[x][y] = '<';
				break;

			case 3:
				map[x][y] = '>';
				break;
			}

			bw.write("#" + tc + " ");
			// 출력
			for (int i = 0; i < H; i++) {
				for (int j = 0; j < W; j++) {
					bw.write(map[i][j]);
				}
				bw.newLine();
			}
		}
		bw.flush();
		bw.close();
	}
}