본문 바로가기
알고리즘 문제풀이/SW Expert

[SW 1873] 상호의 배틀필드

by 선서니 2023. 2. 23.

[문제 바로가기]👇

 

SW Expert Academy

SW 프로그래밍 역량 강화에 도움이 되는 다양한 학습 컨텐츠를 확인하세요!

swexpertacademy.com

 

💡풀이💡

문제에서 제시한 기준에 따라 동작하게 하기!! >> 시뮬레이션

문제를 처음 읽을 때 방향이나 맵 구성 요소가 많아 계속 문제를 참고하면서 했기 때문에 중간 중간에 내가 헷갈리지 않게 하려고 코드를 최대한 깔끔하게 짜려고 했다.

기능 별로 메서드 전부 분리 :: play(), move(), shoot()
탱크 정보 저장 :: Tank 클래스 생성

 

1. 입력 받기

탱크는 무조건 1개만 등장하기 때문에 맵 정보를 받을 때 들어오는 전차의 위치와 방향을 tank 객체에 저장

명령어는 1차원 char 배열로 만들 수 있기 때문에 for문 사용하는 대신 toCharArray 메서드로 바로 만들어줌

class Tank {
	int r;
	int c;
	char dir;
	
	public Tank(int r, int c, char dir) {
		this.r = r;
		this.c = c;
		this.dir = dir;
	}
}

static int R, C, N;
static char[][] map;
static char[] inputs;
static Tank tank;
	
public static void main(String[] args) throws IOException {
	BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
	StringBuilder sb = new StringBuilder();
	int T = Integer.parseInt(br.readLine());
		
	for(int t=1; t<=T; t++) {
		StringTokenizer st = new StringTokenizer(br.readLine(), " ");
		R = Integer.parseInt(st.nextToken());
		C = Integer.parseInt(st.nextToken());
		map = new char[R][C];
			
		for(int i=0; i<R; i++) {
			String str = br.readLine();
			for(int j=0; j<C; j++) {
				map[i][j] = str.charAt(j);
				if(map[i][j]=='^') tank = new Tank(i,j,'u');
				else if(map[i][j]=='v') tank = new Tank(i,j,'d');
				else if(map[i][j]=='<') tank = new Tank(i,j,'l');
				else if(map[i][j]=='>') tank = new Tank(i,j,'r');
			}
		}
			
		N = Integer.parseInt(br.readLine());
		String str = br.readLine();
		inputs = str.toCharArray();
	br.close();
}

 

2. 명령어 실행

명령어는 크게 이동 관련 명령어와 포탄 발사하는

명령어로 나뉘기 때문에 둘로 나누어 메서드를 생성

 

2-1. 포탄 쏘기

위쪽/아래쪽으로 발사이면 현재 탱크의 r 위치를,

왼쪽/오른쪽으로 발사이면 현재 탱크의 c 위치를 가져옴

 

맵 범위를 벗어나거나 벽을 만나면 break

그 외에는 계속 직진

 

📌놓쳤던 부분

맵 범위를 벗어나는 조건과 벽을 만나는 조건을 한번에 if문에 썼기 때문에 벽일 때 벽이 부숴지는 부분 코드에서 범위 체크를 한 번 더 해줬어야 하는데 안 했어서 계속 ArrayIndexOutOfBounds 에러가 났다…

// 벽에 부딪히거나 맵 밖으로 나갈 때까지 직진
static void shoot() {
	// 위쪽으로 발사
	if(tank.dir == 'u') {
		int bomb=tank.r;
		while(true) {
			if(bomb<0 || map[bomb][tank.c]=='*' || map[bomb][tank.c]=='#') {
				if(0<=bomb && map[bomb][tank.c]=='*') map[bomb][tank.c]='.';
				break;
			}
			bomb--;
		}
	}
	// 아래쪽으로 발사
	else if(tank.dir == 'd') {
		int bomb=tank.r;
		while(true) {
			if(bomb>=R || map[bomb][tank.c]=='*' || map[bomb][tank.c]=='#') {
				if(bomb<R && map[bomb][tank.c]=='*') map[bomb][tank.c]='.';
				break;
			}
			bomb++;
		}
	}
	// 왼쪽으로 발사
	else if(tank.dir == 'l') {
		int bomb=tank.c;
		while(true) {
			if(bomb<0 || map[tank.r][bomb]=='*' || map[tank.r][bomb]=='#') {
				if(0<=bomb && map[tank.r][bomb]=='*') map[tank.r][bomb]='.';
				break;
			}
			bomb--;
		}
	}
	// 오른쪽으로 발사
	else {
		int bomb=tank.c;
		while(true) {
			if(bomb>=C || map[tank.r][bomb]=='*' || map[tank.r][bomb]=='#') {
				if(bomb<C && map[tank.r][bomb]=='*') map[tank.r][bomb]='.';
				break;
			}
			bomb++;
		}
	}
}

 

2-2. 이동

명령에 따라 탱크가 지도 범위 안에 있고 이동하려는 방향이 평지이면 탱크 이동하기

탱크의 좌표만 바꾸기 때문에 모든 명령이 끝나고 탱크의 위치에 탱크 방향에 맞게 넣어주기

 

📌놓쳤던 부분

탱크가 이동을 하던 하지 못하던 이동 명령이 들어오면 그 방향으로 탱크의 방향은 무조건 바꿔줘야 한다. 탱크가 이동을 할 때만 방향을 바꾸게 해서 잘못된 결과가 나왔다

// 전차 이동
static void move(char order) {
	map[tank.r][tank.c] = '.';
	if(order == 'U') {
		tank.dir = 'u';
		if(0<=tank.r-1 && map[tank.r-1][tank.c]=='.') tank.r-=1;
	}
	else if(order == 'D') {
		tank.dir = 'd';
		if(tank.r+1<R && map[tank.r+1][tank.c]=='.') tank.r+=1;
	}
	else if(order == 'L') {
		tank.dir = 'l';
		if(0<=tank.c-1 && map[tank.r][tank.c-1]=='.') tank.c-=1;
	}
	else {
		tank.dir = 'r';
		if(tank.c+1<C && map[tank.r][tank.c+1]=='.') tank.c +=1;
	}
}

// 명령 끝난 후 탱크 위치 저장
if(tank.dir=='u') map[tank.r][tank.c] = '^';
else if(tank.dir=='d') map[tank.r][tank.c] = 'v';
else if(tank.dir=='l') map[tank.r][tank.c] = '<';
else if(tank.dir=='r') map[tank.r][tank.c] = '>';

 

전체 코드

package ps_02222;

import java.io.*;
import java.util.*;

class Tank {
	int r;
	int c;
	char dir;
	
	public Tank(int r, int c, char dir) {
		this.r = r;
		this.c = c;
		this.dir = dir;
	}
}

public class SW1873 {
	static int R, C, N;
	static char[][] map;
	static char[] inputs;
	static Tank tank;
	
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringBuilder sb = new StringBuilder();
		int T = Integer.parseInt(br.readLine());
		
		for(int t=1; t<=T; t++) {
			StringTokenizer st = new StringTokenizer(br.readLine(), " ");
			R = Integer.parseInt(st.nextToken());
			C = Integer.parseInt(st.nextToken());
			map = new char[R][C];
			
			for(int i=0; i<R; i++) {
				String str = br.readLine();
				for(int j=0; j<C; j++) {
					map[i][j] = str.charAt(j);
					if(map[i][j]=='^') tank = new Tank(i,j,'u');
					else if(map[i][j]=='v') tank = new Tank(i,j,'d');
					else if(map[i][j]=='<') tank = new Tank(i,j,'l');
					else if(map[i][j]=='>') tank = new Tank(i,j,'r');
				}
			}
			
			N = Integer.parseInt(br.readLine());
			String str = br.readLine();
			inputs = str.toCharArray();
			
			for(int i=0; i<N; i++) {
				play(inputs[i]);
			}
			
			// 명령 끝난 후 탱크 위치 저장
			if(tank.dir=='u') map[tank.r][tank.c] = '^';
			else if(tank.dir=='d') map[tank.r][tank.c] = 'v';
			else if(tank.dir=='l') map[tank.r][tank.c] = '<';
			else if(tank.dir=='r') map[tank.r][tank.c] = '>';
			
			sb.append("#").append(t).append(" ");
			for(int i=0; i<R; i++) {
				for(int j=0; j<C; j++) {
					sb.append(map[i][j]);
				}
				sb.append("\\n");
			}
		}
		System.out.println(sb.toString());
		br.close();
	}
	
	static void play(char order) {
		if(order == 'S') shoot();
		else move(order);
	}
	
	// 전차 이동
	static void move(char order) {
		map[tank.r][tank.c] = '.';
		if(order == 'U') {
			tank.dir = 'u';
			if(0<=tank.r-1 && map[tank.r-1][tank.c]=='.') tank.r-=1;
		}
		else if(order == 'D') {
			tank.dir = 'd';
			if(tank.r+1<R && map[tank.r+1][tank.c]=='.') tank.r+=1;
		}
		else if(order == 'L') {
			tank.dir = 'l';
			if(0<=tank.c-1 && map[tank.r][tank.c-1]=='.') tank.c-=1;
		}
		else {
			tank.dir = 'r';
			if(tank.c+1<C && map[tank.r][tank.c+1]=='.') tank.c +=1;
		}
	}
	
	
	// 벽에 부딪히거나 맵 밖으로 나갈 때까지 직진
	static void shoot() {
		// 위쪽으로 발사
		if(tank.dir == 'u') {
			int bomb=tank.r;
			while(true) {
				if(bomb<0 || map[bomb][tank.c]=='*' || map[bomb][tank.c]=='#') {
					if(0<=bomb && map[bomb][tank.c]=='*') map[bomb][tank.c]='.';
					break;
				}
				bomb--;
			}
		}
		// 아래쪽으로 발사
		else if(tank.dir == 'd') {
			int bomb=tank.r;
			while(true) {
				if(bomb>=R || map[bomb][tank.c]=='*' || map[bomb][tank.c]=='#') {
					if(bomb<R && map[bomb][tank.c]=='*') map[bomb][tank.c]='.';
					break;
				}
				bomb++;
			}
		}
		// 왼쪽으로 발사
		else if(tank.dir == 'l') {
			int bomb=tank.c;
			while(true) {
				if(bomb<0 || map[tank.r][bomb]=='*' || map[tank.r][bomb]=='#') {
					if(0<=bomb && map[tank.r][bomb]=='*') map[tank.r][bomb]='.';
					break;
				}
				bomb--;
			}
		}
		// 오른쪽으로 발사
		else {
			int bomb=tank.c;
			while(true) {
				if(bomb>=C || map[tank.r][bomb]=='*' || map[tank.r][bomb]=='#') {
					if(bomb<C && map[tank.r][bomb]=='*') map[tank.r][bomb]='.';
					break;
				}
				bomb++;
			}
		}
	}
}

'알고리즘 문제풀이 > SW Expert' 카테고리의 다른 글

[SW Expert 1953] 탈주범 검거  (0) 2023.04.04
[SW Expert 5656] 벽돌 깨기  (0) 2023.02.25
[SW 1247] 최적 경로  (0) 2023.02.23
[SW Expert 5215] 햄버거 다이어트  (0) 2023.02.16
[SW Expert 4012] 요리사  (2) 2023.02.16

댓글