본문 바로가기
알고리즘

BOJ 8972 - 미친 아두이누(Java)

by 장중앙 2022. 1. 14.

https://www.acmicpc.net/problem/8972

 

8972번: 미친 아두이노

요즘 종수는 아두이노를 이용해 "Robots"이라는 게임을 만들었다. 종수는 아두이노 한대를 조정하며, 미친 아두이노를 피해다녀야 한다. 미친 아두이노는 종수의 아두이노를 향해 점점 다가온다.

www.acmicpc.net

 

풀이

플레이어의 이동 명령만큼 1~6을 반복, 미친 아두이노와 플레이어 아두이노가 겹치면 게임 종료

1. 종수(플레이어) 이동

2. 이동 횟수 ++

3. 플레이어가 죽었는지 확인

4. 미친 아두이노 이동

5. 플레이어가 죽었는지 확인

6. 겹치는 미친 아두이누 폭발

 

 


미친 아두이노의 위치 정보를  2차원 배열 List와 List를 이용해 관리

static List<Integer>[][] map;
static List<Pos> crazyArduinos = new ArrayList<>();
static Pos player;

static class Pos {
	int y, x, num;

	Pos(int y, int x) {
		this.y = y;
		this.x = x;
		this.num = -1;
	}

	Pos(int y, int x, int num) {
		this.y = y;
		this.x = x;
		this.num = num;
	}
}

플레이어 이동

플레이어와 아두이노의 이동 방향 결정 0 : 안씀, 5 : 위치 그대로

static int[] dy = {0, 1, 1, 1, 0, 0, 0, -1, -1, -1};
static int[] dx = {0, -1, 0, 1, -1, 0, 1, -1, 0, 1};

입력받은 이동 명령에 따라 다음 위치를 결정

private static void playerGo(int command) {
	if (command == 5)
		return;
	player.y = player.y + dy[command];
	player.x = player.x + dx[command];
}

플레이어가 죽었는지 확인

미친 아두이노가 있는 위치를 나타내는 2차원 배열 List에 플레이어의 위치를 대입

사이즈가 0이 아니라면 해당 위치에 미친 아두이노가 있기 때문에 게임오버

private static boolean isPlayerDead() {
	if (map[player.y][player.x].size() == 0) return false;
	else return true;
}

미친 아두이노 이동

이차원 배열 List의 모든 기록 삭제

List에 담긴 미친 아두이노의 현재위치를 순회하여 미친 아두이노의 다음 위치 결정

closetChoice()함수로 플레이어와 가장 가까운 위치를 향하는 방향을 결정

해당 방향으로 이동 - List에 담긴 미친 아두이노의 현재위치 수정, 이차원 배열 List의 위치에 add

 private static void CrazyGo() {
	for (int i = 0; i < R; i++) {
		for (int j = 0; j < C; j++) {
			map[i][j].clear();
		}
	}

	for (int i = 0; i < crazyArduinos.size(); i++) {
		int y = crazyArduinos.get(i).y;
		int x = crazyArduinos.get(i).x;
		int dir = closestChoice(y, x);

		int ny = y + dy[dir];
		int nx = x + dx[dir];
		crazyArduinos.get(i).y = ny;
		crazyArduinos.get(i).x = nx;
		map[ny][nx].add(crazyArduinos.get(i).num);
	}
}

미친 아두이노의 현재 위치를 매개변수로 플레이어와 가장 가까운 위치를 향하는 방향을 결정

상하좌우, 대각 8가지 방향에 대한 다음위치와 플레이어의 위치의 거리를 계산하여 가장 가까운 거리를 가진 방향을 return

private static int closestChoice(int y, int x) {
	int minDist = 987654321;
	int minDir = 0;
	
    for (int dir = 1; dir <= 9; dir++) {
		if (dir == 5) continue;
		int ny = y + dy[dir];
		int nx = x + dx[dir];
		
		int dist = Math.abs(ny - player.y) + Math.abs(nx - player.x);
		if (minDist > dist) {
			minDist = dist;
			minDir = dir;
		}
    return minDir
}

겹치는 아두이노 폭발

미친 아두이노의 위치정보가 담긴 List clear, 이차원 배열 List의 모든 위치를 탐색

현재 위치의 사이즈가 1이라면 겹치는 아두이노가 없기 때문에 정보 그대로 -> List에 add

현재 위치의 사이즈가 2이상이라면 겹치는 아두이노가 있기 때문에 해당 미친 아두이노를 삭제해야함

  -> 2차원 배열 List의 현재 위치를 clear

private static void bombCrazy() {
	crazyArduinos.clear();
	for (int i = 0; i < R; i++) {
		for (int j = 0; j < C; j++) {
			if (map[i][j].size() == 1) crazyArduinos.add(new Pos(i, j, map[i][j].get(0)));
			else if (map[i][j].size() >= 2) map[i][j].clear();
		}
	}
}

전체 코드

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

public class Main {
    static int R, C;
    static List<Integer>[][] map;
    static int[] dy = {0, 1, 1, 1, 0, 0, 0, -1, -1, -1};
    static int[] dx = {0, -1, 0, 1, -1, 0, 1, -1, 0, 1};
    static List<Pos> crazyArduinos = new ArrayList<>();
    static Pos player;


    static class Pos {
        int y, x, num;

        Pos(int y, int x) {
            this.y = y;
            this.x = x;
            this.num = -1;
        }

        Pos(int y, int x, int num) {
            this.y = y;
            this.x = x;
            this.num = num;
        }
    }

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
//        BufferedReader br = new BufferedReader(new FileReader("a.txt"));

        StringTokenizer st = new StringTokenizer(br.readLine());
        R = Integer.parseInt(st.nextToken());
        C = Integer.parseInt(st.nextToken());
        map = new ArrayList[R][C];
        int arduinoIdx = 1;

        for (int i = 0; i < R; i++) {
            char[] temp = br.readLine().toCharArray();
            for (int j = 0; j < temp.length; j++) {
                map[i][j] = new ArrayList<Integer>();
                if (temp[j] == 'I') {
                    player = new Pos(i, j);
                } else if (temp[j] == 'R') {
                    crazyArduinos.add(new Pos(i, j, arduinoIdx));
                    map[i][j].add(arduinoIdx++);
                }
            }
        }

        char[] commands = br.readLine().toCharArray();
        int cnt = 0;
        for (char c : commands) {
            playerGo(c - '0');
            cnt++;
            if (isPlayerDead()) break;

            CrazyGo();
            if (isPlayerDead()) break;

            bombCrazy();
        }
        
        if (cnt < commands.length) {
            System.out.println("kraj " + cnt);
        } else {
            printMap();
        }
    }

    private static void printMap() {
        char arr[][] = new char[R][C];
        for (int i = 0; i < R; i++) {
            Arrays.fill(arr[i], '.');
        }
        
        arr[player.y][player.x] = 'I';
        
        for (Pos p : crazyArduinos) {
            arr[p.y][p.x] = 'R';
        }

        for (int i = 0; i < R; i++) {
            System.out.println(arr[i]);
        }
    }
    // 겹치는 미친 아두이노 폭발
    private static void bombCrazy() {
        crazyArduinos.clear();
        for (int i = 0; i < R; i++) {
            for (int j = 0; j < C; j++) {
                if (map[i][j].size() == 1) crazyArduinos.add(new Pos(i, j, map[i][j].get(0)));
                else if (map[i][j].size() >= 2) map[i][j].clear();
            }
        }
    }
	
    // 미친 아두이노 이동
    private static void CrazyGo() {
        for (int i = 0; i < R; i++) {
            for (int j = 0; j < C; j++) {
                map[i][j].clear();
            }
        }

        for (int i = 0; i < crazyArduinos.size(); i++) {
            int y = crazyArduinos.get(i).y;
            int x = crazyArduinos.get(i).x;
            int dir = closestChoice(y, x);

            int ny = y + dy[dir];
            int nx = x + dx[dir];
            crazyArduinos.get(i).y = ny;
            crazyArduinos.get(i).x = nx;
            map[ny][nx].add(crazyArduinos.get(i).num);
        }
    }
    
	// 미친 아두이노가 플레이어와 가까워지는 방향 탐색
    private static int closestChoice(int y, int x) {
        int minDist = 987654321;
        int minDir = 0;
        for (int dir = 1; dir <= 9; dir++) {
            if (dir == 5) continue;
            int ny = y + dy[dir];
            int nx = x + dx[dir];
            int dist = Math.abs(ny - player.y) + Math.abs(nx - player.x);
            if (minDist > dist) {
                minDist = dist;
                minDir = dir;
            }
        }
        return minDir;
    }
	
    // 플레이어 이동
    private static void playerGo(int command) {
        if (command == 5)
            return;
        player.y = player.y + dy[command];
        player.x = player.x + dx[command];
    }
	
    // 플레이어가 죽었는지 확인
    // 플레이어의 위치와 같은 위치인 미친 아두이노가 있는지 탐색
    private static boolean isPlayerDead() {
        if (map[player.y][player.x].size() == 0) return false;
        else return true;
    }
}

댓글