코테/백준

[백준/JAVA] 4396번: 지뢰 찾기

imname1am 2023. 12. 13. 01:11
반응형

🔺 문제

 

4396번: 지뢰 찾기

지뢰찾기는 n × n 격자 위에서 이루어진다. m개의 지뢰가 각각 서로 다른 격자 위에 숨겨져 있다. 플레이어는 격자판의 어느 지점을 건드리기를 계속한다. 지뢰가 있는 지점을 건드리면 플레이어

www.acmicpc.net

 

 

🧩  해결 아이디어

• 구현

  • 필요 변수
    • char형 2차원 격자 배열
    • 열렸는지 확인용 boolean형 2차원 방문 배열
    • 지뢰 갯수 저장할 int형 2차원 배열
    • 지뢰 건드렸는지 확인용 boolean 변수

 

  1. 지뢰 위치를 2차원 char형 배열로 입력받는다.
  2. 열린 칸과 안 열린 칸을 입력 받는다.
    • 해당 칸이 열렸을 경우, 해당 칸은 방문 처리
      • 지뢰가 아닌 칸이 열린 경우, 8방향을 돌며 주변 지뢰 갯수를 센다.
      • 지뢰인 칸이 열린 경우, 입력받을 때 지뢰였던 칸은 '*'로 출력하게 한다. → boolean 변수 활용해 지뢰인 칸 열렸는지 판별
  3. 출력한다.
    • 지뢰 안 건드린 경우, 방문 안 한 모든 칸을 '.'으로 출력.
    • 지뢰를 건드린 경우, 방문 안 한 칸 中 지뢰인 칸은 '*'으로 출력.

 

 

💥 유의사항

지뢰인 칸이 열린 경우, 바로 break하면 뒤쪽에서 주변의 지뢰 갯수를 셀 수 없게 된다..

 

 

🔺 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
import java.util.*;
import java.io.*;
 
public class Main {
    static int[] dx = {0,0,-1,1-1-111};   // 상하좌우 대각선 8방향
    static int[] dy = {1,-1,0,0-111-1};
 
    static int N;
    static char[][] board;      // 2차원 격자 배열
    static boolean[][] visited; // 방문 배열
    static int[][]  ans;        // 지뢰 갯수 저장 배열
 
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
 
        N = Integer.parseInt(br.readLine());
        board = new char[N][N];
        ans = new int[N][N];
        visited = new boolean[N][N];
 
        // 1. 지뢰 위치 입력받기
        for(int i = 0 ; i < N ; i++) {
            String str = br.readLine();
            for(int j = 0 ; j < N ; j++) {
                board[i][j] = str.charAt(j);
            }
        }
 
        // 2. 열린 / 안 열린 칸 입력받기
        boolean touchBomb = false; // 지뢰 눌렸는지 확인용 변수
 
        for(int i = 0 ; i < N ; i++) {
            String str = br.readLine();
            for(int j = 0 ; j < N ; j++) {
                char ch = str.charAt(j);
 
                // 열린 경우
                if(ch == 'x') {
                    // 지뢰 아닌 칸이 열린 경우, 주변 지뢰 갯수 세서 배열에 저장
                    if(board[i][j] == '.') {
                        visited[i][j] = true;
                        countBombs(i, j);
                    }
                    // 지뢰인 칸이 열린 경우
                    else {
                        touchBomb = true;
                    }
                }
 
            }
        }
 
        // 3. 출력하기
        StringBuilder sb = new StringBuilder();
        for(int i = 0 ; i < N ; i++) {
            for(int j = 0 ; j < N ; j++) {
                // 지뢰 안 건드린 경우, 방문 안 한 모든 칸을 '.'으로 출력
                if(!touchBomb) {
                    if(visited[i][j]) {
                        sb.append(ans[i][j]);
                    }
                    else {
                        sb.append(".");
                    }
                }
                // 지뢰 건드린 경우, 방문 안 한 칸 中 지뢰인 칸은 '*'으로 출력
                else {
                    if(visited[i][j]) {
                        sb.append(ans[i][j]);
                    }
                    else {
                        if(board[i][j] == '*') {
                            sb.append('*');
                        }
                        else {
                            sb.append(".");
                        }
                    }
                }
            }
            sb.append("\n");
        }
        System.out.println(sb);
    }
 
    // 현재 위치 주변의 지뢰 갯수 세는 함수
    private static void countBombs(int x, int y) {
        for(int d = 0 ; d < 8 ; d++) {
            int nx = x + dx[d];
            int ny = y + dy[d];
 
            if(!inRange(nx, ny))    continue;
 
            if(board[nx][ny] == '*') {
                ans[x][y]++;
            }
        }
    }
 
    // 격자 범위 내에 있는지 판별하는 함수
    private static boolean inRange(int x, int y) {
        return (0 <= x && x < N && 0 <= y && y < N);
    }
}
cs
 

 


🔺 다른 풀이들

- 2차원 방문 배열도 두지 않으시고,

격자 배열과 지뢰 갯수 저장할 배열을 아예 하나로 만드셨다.

그리고 int형 변수 cnt 활용하신 풀이가 많았다.

board[i][j] = (char) (cnt + '0');
 

백준 4396 지뢰 찾기 (JAVA)

문제 https://www.acmicpc.net/problem/4396 4396번: 지뢰 찾기 지뢰찾기는 n × n 격자 위에서 이루어진다. m개의 지뢰가 각각 서로 다른 격자 위에 숨겨져 있다. 플레이어는 격자판의 어느 지점을 건드리기를

goto-pangyo.tistory.com

 


💬 느낀 점

담엔 나도 저렇게 풀어봐야지,,,

boolean방문 배열 안 쓰신 풀이가 많아서 놀랐다,,

 

1회독 2회독 3회독 4회독 5회독
V 12.25      

 

 

(+12.25 2회독)

visited 방문배열 사용하지 않고 작성했다.

이번에도 지뢰 눌렀을 때 출력 처리를 제대로 못 해서 반례를 보고 코드를 수정해 풀었다ㅠ

 

코드 확인하기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
import java.util.*;
import java.io.*;
 
public class Main {
    static int[] dx = {-1,-1,-1,0,0,1,1,1};   // 상하좌우 대각선
    static int[] dy = {-1,0,1,-1,1,-1,0,1};
    
    static int N;
    static char[][] board, result;
    static StringBuilder sb = new StringBuilder();
    
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        N = Integer.parseInt(br.readLine());
        
        board = new char[N][N];
        for(int i = 0 ; i < N ; i++) {
            String str = br.readLine();
            for(int j = 0 ; j < N ; j++) {
                board[i][j] = str.charAt(j);
            }
        }
        
        boolean bomb = false;
        result = new char[N][N];
        
        for(int i = 0 ; i < N ; i++) {
            String str = br.readLine();
            for(int j = 0 ; j < N ; j++) {
                if(str.charAt(j) == 'x') {
                    if(board[i][j] == '.') {
                        cntAround(i, j);
                    }
                    else {
                        bomb = true;
                    }
                }
                else {
                    result[i][j] = '.';
                }
            }
        }
        
        if(bomb) {
            printBomb();
        }
        else {
            printAns();
        }
        System.out.println(sb);
    }
    
    private static void cntAround(int x, int y) {
        int cnt = 0;
        
        for(int dir = 0 ; dir < 8 ; dir++) {
            int nx = x + dx[dir];
            int ny = y + dy[dir];
            
            if(inRange(nx, ny) && board[nx][ny] == '*') {
                cnt++;
            }
        }
        
        result[x][y] = (char)(cnt + '0');
    }
    
    private static boolean inRange(int x, int y) {
        return (0 <= x && x < N && 0 <= y && y < N);
    }
    
    private static void printBomb() {
        for(int i = 0 ; i < N ; i++) {
            for(int j = 0 ; j < N ; j++) {
                if(board[i][j] == '*')
                    result[i][j] = '*';
                sb.append(result[i][j]);
            }
            sb.append("\n");
        }
        return;
    }
    
    private static void printAns() {
        for(char[] chArr : result) {
            for(char ch : chArr) {
                sb.append(ch);
            }
            sb.append("\n");
        }
        return;
    }
}
 
cs


(참고)

✔ TC 참고

 

글 읽기 - 테스트 케이스입니다.

댓글을 작성하려면 로그인해야 합니다.

www.acmicpc.net

 

반응형