다음 그림과 같이 지뢰가 있는 지역과 지뢰에 인접한 위, 아래, 좌, 우 대각선 칸을 모두 위험지역으로 분류합니다.

지뢰는 2차원 배열 board에 1로 표시되어 있고 board에는 지뢰가 매설 된 지역 1과, 지뢰가 없는 지역 0만 존재합니다.
지뢰가 매설된 지역의 지도 board가 매개변수로 주어질 때, 안전한 지역의 칸 수를 return하도록 solution 함수를 완성해주세요.
보자마자 떠올랐던 건 프로그래머스 기초 문제 중 제일 어려웠던 정수를 나선형으로 배치하기 문제였다. 그때, 방향을 바꾸어줄 변수를 따로 만들었던 게 생각이 나서 이번에도 그 방법을 이용해 보기로 했다.
다만 지난 문제보다 복잡했던 건 대각선도 생각해 주어야 하고, board의 범위를 벗어나는 경우는 제외해 주어야 한다는 것이었다. 우선 정사각형인 board의 길이를 변수 n에 저장한 뒤, 지뢰가 있는 + 위험 지역을 표시할 새로운 2차원 배열 dangerZone을 만든다.
다음으로는 방향 벡터를 만들어 주어야 하는데, 여러 번 사용할 것이기 때문에 루프를 돌며 체크할 수 있도록 변수가 아닌 배열에 저장해 주었다. 이때 x와 y는 따로 만들며 각 방향에 맞게 인덱스 값을 바꾸어줄 수 있도록 벡터 값을 넣는다. 예를 들자면 (-1, 0)은 상, (-1, 1)은 우상, (1, -1)은 좌하가 되는 것이다.
이제 for문을 돌며 주어진 board에 지뢰가 있을 때 = 값이 1일 때, dangerZone에 위험 지역까지 함께 체크해 주면 된다. if(board[i][j] == 1)인 경우, dangerZone에도 동일하게 dangerZone[i][j] = 1; 표시한다. 다음으로는 방향 벡터(dx, dy)를 이용해 위험 지역을 체크한다. 범위는 0~7까지 총 8이고, 지뢰가 있는 지역의 인덱스인 i와 j에 벡터 값들을 차례로 더해 dangerZone에 표시할 새로운 인덱스 값을 만든다.
이때 중요한 것은 앞서 말했듯 board의 범위를 벗어나지 않는지 체크해야 한다는 것이다.
- 체크할 x 좌표가 0 이상인지 :
ni >= 0- 체크할 x 좌표가 n-1 이하인지 :
ni < n- 인덱스는 0부터 시작하기 때문- y 좌표 위와 동일 :
nj >= 0 && nj < n
위 사항을 모두 통과하면 그때, dangerZone[ni][nj] = 1; 해준다. 체크가 끝나면, dangerZone[i][j] == 0일 때마다 +1 해주어 안전 지역을 계산해 반환한다.
class Solution {
public int solution(int[][] board) {
int n = board.length;
int[][] dangerZone = new int[n][n];
int[] dx = {-1, 1, 0, 0, -1, -1, 1, 1};
int[] dy = {0, 0, -1, 1, -1, 1, -1, 1};
for(int i=0; i<n; i++){
for(int j=0; j<n; j++){
if(board[i][j] == 1){
dangerZone[i][j] = 1;
for(int d=0; d<8; d++){
int ni = i + dx[d];
int nj = j + dy[d];
if(ni >= 0 && ni < n && nj >= 0 && nj < n){
dangerZone[ni][nj] = 1;
}
}
}
}
}
int safeCount = 0;
for(int i=0; i<n; i++){
for(int j=0; j<n; j++){
if(dangerZone[i][j] == 0){
safeCount += 1;
}
}
}
return safeCount;
}
}
