
N * N 크기의 오목판
돌이 가로, 세로, 대각선 중 하나의 방향으로 다섯 개 이상 연속한 부분이 있는지 없는지 판정
. : 돌이 없음
o : 돌이 있음
// 입력
1
5
....o
...o.
..o..
.o...
o....
➡️ ⬇️ ↘️ ↙️
int[] dx = {0, 1, 1, 1};
int[] dy = {1, 0, 1, -1};
import java.util.Scanner;
public class Solution {
public static void main(String[] args) {
Scanner sc = new Scanner (System.in);
// [input]
int T = sc.nextInt();
for(int t = 1; t <=T; t++) {
int N = sc.nextInt();
sc.nextLine();
// N * N 오목
char[][] Narr = new char[N][N];
// N줄, N길이의 문자열 -> 배열에 담기
for(int n=0; n<N; n++) {
String string = sc.nextLine();
for(int m=0; m<N;m++) {
Narr[n][m]=string.charAt(m);
}
}//for n
// [logic]
// 4가지 방향 : (오른쪽) - | \ /
int[] dx = {0, 1, 1, 1};
int[] dy = {1, 0, 1, -1};
// 플래그 변수
boolean isFound = false;
// 오목판 탐색 반복 조건: 연속된 5개 이상의 돌이 발견 X
for(int x=0; x<N && !isFound; x++) {
for(int y=0; y<N && !isFound ; y++) {
// 현재 돌이 있다면
if(Narr[x][y]=='o') {
// 4방향 탐색
for(int d=0; d<4; d++) {
// 각 방향으로 4개의 돌이 있는가
int cnt = 1;
for(int i=1; i<=4; i++) {
int nx = x + dx[d]*i;
int ny = y +dy[d]*i;
// 이동한 좌표값이 유효한가
if(nx>=0 && nx<N && ny>=0 && ny < N) {
if(Narr[nx][ny]=='o') {
++cnt;
}
else break;
}
}// for: 4i
// 조건 고민 (최소 4칸까지만 이동하므로)
if(cnt==5) {
isFound = true;
break;
}
}// for: 4d
}//if: o
}//for: y
}// for: x
// [output]
System.out.println("#" + t + " " + (isFound ? "YES" : "NO"));
}// for: T
}
}
[개선 방향]
1. 불필요한 범위 검사 최소화 (시작점 조건 추가)
2. 연속 5개 확인 루프 단순화
3. 반복문 깊이 줄이기 위해 방향별 체크 함수로 분리
1) 방향 벡터의 정의
? 처음에는 8방향(상, 하, 좌, 우, 대각선 4개) 모두 검사해야 하나 고민함
! 오목판은 대칭 구조이므로, 오른쪽, 아래, 두 대각선 ↘, ↗만 검사해도 다른 시작점에서 나머지 방향이 커버됨 => 4방향
2) 중첩 루프 탈출 & 플래그 변수의 활용
? 오목판 전체를 탐색해야 해서 중첩된 for문이 많음
연속 5개 돌을 발견한 순간 전체 탐색을 중단해야 하는데, break만으로는 아우터 루프까지 빠져나오기 어려움
! 플래그 변수를 사용해서 외부 루프까지 결과 전달
함수 분리 후 return -> 바로 탈출 가능, 가독성 향상