https://school.programmers.co.kr/learn/courses/30/lessons/120866
난 참 예외처리에 약하다.(경험부족..) 이론을 계속봐도 이론과 실습의 괴리가 너무 큰 파트같다. 이번 문제에서 인덱스예외처리를 해결하는 아이디어 조차도 나는 잘 떠올리지 못했다.
IndexOutOfBoundsException 에러를 잡지 못해서 결국 해결책을 컨닝했다.
오류와 해결방식은 간단했다.
지뢰가 위치한 셀이 보드의 가장자리일 경우는 주변셀이 이미 없으므로 위험지역으로 처리하기 위한 코드에서 각각 +1, -1을 해버릴때 인덱스의 범위를 벗어나는 오류였다.
위험지역 가능성이 있는 셀들을 모두 if문으로 범위를 체크한다.
class Solution {
public int solution(int[][] board) {
int answer = 0;
String[][] arr = new String[board.length][board.length];
//새 2차배열 arr에 지뢰좌표와 일치한 인덱스의 요소에 x를 대입한다.
for(int i = 0; i < board.length; i++) {
for(int j = 0; j < board.length; j++) {
if(board[i][j] == 1) {
arr[i][j] = "x";
} else arr[i][j] = "o";
}
}
//요소값이 x인 arr배열의 인덱스를 반환하여 board배열에 대입, 위험지역을 1로 바꿔준다.
for(int i = 0; i < arr.length; i++) {
for(int j = 0; j < arr.length; j++) {
if(arr[i][j].equals("x")) {
//가장자리에 위치한 지뢰의 경우, IndexOutOfBoundsException 예외처리 필요.
if(i > 0) board[i-1][j] = 1;
if(i < arr.length-1) board[i+1][j] = 1;
if(j > 0) board[i][j-1] = 1;
if(j < arr.length-1) board[i][j+1] = 1;
if(i > 0 && j > 0) board[i-1][j-1] = 1;
if(i < arr.length-1 && j > 0) board[i+1][j-1] = 1;
if(i > 0 && j < arr.length-1) board[i-1][j+1] = 1;
if(i < arr.length-1 && j < arr.length-1) board[i+1][j+1] = 1;
}
}
}
//최종적으로 안전지역(0인 지역)의 수를 셈한다.
for(int i = 0; i < board.length; i++) {
for(int j = 0; j < board.length; j++) {
if(!(board[i][j] == 1)) answer++;
}
}
return answer;
}
}
1. 객체지향적 접근! 위험지역을 확인하는 세부동작은 메서드화 하자.
2. 8줄의 if문 향연..을 심플하게 줄여보자.
class Solution {
public int solution(int[][] board) {
int answer = 0;
//지뢰가 있는 셀 찾기
for(int i = 0; i < board.length; i++) {
for(int j = 0; j < board.length; j++) {
if(board[i][j] == 1) {
//위험지역으로 분류하기
changeDangerCell(board, i, j);
}
}
}
//안전지역인 셀 수 반환하기
for(int i = 0; i < board.length; i++) {
for(int j = 0; j < board.length; j++) {
if(board[i][j] == 0) answer++;
}
}
return answer;
}
//지뢰에 인접한 8개의 셀을 위험지역으로 분류하는 메서드
public void changeDangerCell(int[][] board, int i, int j) {
int length = board.length;
//인접한 8개의 셀의 좌표값을 가진 배열
int[][] directions = {{0,-1},{0,1},{-1,-1},{-1,0},{-1,1},{1,-1},{1,0},{1,1}};
for(int[] dir : directions) {
int x = i + dir[0];
int y = j + dir[1];
//보드의 가장자리이거나 이미 지뢰가 매설된 지역이 아니면 위험지역(-1)로 분류하기
if(x >= 0 && y >= 0 && x < length && y < length && board[x][y] == 0) {
board[x][y] = -1;
}
}
}
}
board[x][y] == 0
처럼 조건을 걸어서 지뢰가 아닌 셀만 위험지역으로 바꾸면 된다.. 초간단. 🤦♀️
그리고, if문으로 일일이 나열했던 코드는 위험지역 가능성이 있는 좌표값을 배열에 담아 반복문으로 돌리는 동작으로 수정할 수 있다.