티스토리 뷰
문제
오목은 바둑판에 검은 바둑알과 흰 바둑알을 교대로 놓아서 겨루는 게임이다. 바둑판에는 19개의 가로줄과 19개의 세로줄이 그려져 있는데 가로줄은 위에서부터 아래로 1번, 2번, ... ,19번의 번호가 붙고 세로줄은 왼쪽에서부터 오른쪽으로 1번, 2번, ... 19번의 번호가 붙는다.
위의 그림에서와 같이 같은 색의 바둑알이 연속적으로 다섯 알을 놓이면 그 색이 이기게 된다. 여기서 연속적이란 가로, 세로 또는 대각선 방향 모두를 뜻한다. 즉, 위의 그림은 검은색이 이긴 경우이다. 하지만 여섯 알 이상이 연속적으로 놓인 경우에는 이긴 것이 아니다.
입력으로 바둑판의 어떤 상태가 주어졌을 때, 검은색이 이겼는지, 흰색이 이겼는지 또는 아직 승부가 결정되지 않았는지를 판단하는 프로그램을 작성하시오. 단, 검은색과 흰색이 동시에 이기거나 검은색 또는 흰색이 두 군데 이상에서 동시에 이기는 경우는 입력으로 들어오지 않는다.
입력
19줄에 각 줄마다 19개의 숫자로 표현되는데, 검은 바둑알은 1, 흰 바둑알은 2, 알이 놓이지 않는 자리는 0으로 표시되며, 숫자는 한 칸씩 띄어서 표시된다.
출력
첫줄에 검은색이 이겼을 경우에는 1을, 흰색이 이겼을 경우에는 2를, 아직 승부가 결정되지 않았을 경우에는 0을 출력한다. 검은색 또는 흰색이 이겼을 경우에는 둘째 줄에 연속된 다섯 개의 바둑알 중에서 가장 왼쪽에 있는 바둑알(연속된 다섯 개의 바둑알이 세로로 놓인 경우, 그 중 가장 위에 있는 것)의 가로줄 번호와, 세로줄 번호를 순서대로 출력한다.
Baekjoon
나는 크게 4가지 방향(오른쪽, 아래, 왼쪽 대각선, 오른쪽 대각선)을 기준으로 5개의 바둑알이 연속하여 나타나는지를 확인하였다. 현재 방향으로 탐색을 진행할 때, 다음 바둑돌도 같은 색을 가지고 있다면, 바둑돌의 수가 5가 될 때까지 같은 방향으로 탐색을 진행한다.
같은 색의 5개의 바둑돌을 찾았다면, 첫번째 바둑돌의 이전 위치와 다섯번째 바둑돌의 다음 위치의 바둑돌의 색을 체크한다. (같은 색의 바둑돌이 5개를 넘어서 나타면 x) 만약 하나라도 같은 색을 가지고 있다면, 다시 탐색을 진행하고 둘다 다르다면 모든 탐색을 종료하고 출력한다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Solution2615H {
static int[][] board;
static int[][] dir = {{0, 1}, {1, 0}, {1, 1}, {1, -1}}; // 우 - 하 - 우하 - 좌하
static StringBuilder answer;
public static void main(String[] args) throws IOException {
// 입력
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
answer = new StringBuilder();
// 오목판 생성
board = new int[19][19];
for (int line = 0; line < 19; line++) {
StringTokenizer st = new StringTokenizer(br.readLine(), " ");
for (int i = 0; i < 19; i++) {
board[line][i] = Integer.parseInt(st.nextToken());
}
}
// 모든 경우 탐색
loop:
for (int x = 0; x < 19; x++) {
for (int y = 0; y < 19; y++) {
if (board[x][y] == 0) continue;
if (playGame(x, y)) break loop;
}
}
System.out.println(answer.length() == 0 ? "0" : answer);
}
// 게임 시작
private static boolean playGame(int x, int y) {
// 현재 바둑돌 색 저장
int current = board[x][y];
// 방향 탐색
for (int idx = 0; idx < 4; idx++) {
// 탐색 방향 설정
int nx = x + dir[idx][0];
int ny = y + dir[idx][1];
// 탐색 가능한지 확인 (범위 + 같은 색인지)
if (!isIn(nx, ny) || board[nx][ny] != current) continue;
// 게임 승부가 결정 됐다면
if (search(nx, ny, current, idx)) {
// 이전 위치의 바둑돌 확인
int prevX = x - dir[idx][0];
int prevY = y - dir[idx][1];
if (!isIn(prevX, prevY) || board[prevX][prevY] != current) {
// 좌측 아래방향을 탐색할 경우, 바둑알 좌표 설정
if (idx == 3) {
answer.append(board[x + 4][y - 4]).append("\n");
answer.append(x + 5).append(" ").append(y - 3);
} else {
answer.append(board[x][y]).append("\n");
answer.append(x + 1).append(" ").append(y + 1);
}
return true;
}
}
}
return false;
}
// 탐색
private static boolean search(int x, int y, int current, int idx) {
int cnt = 2;
while (true) {
int nx = x + dir[idx][0];
int ny = y + dir[idx][1];
if (cnt == 5) {
// 다음 위치의 바둑돌 확인
if (!isIn(nx, ny) || board[nx][ny] != current) {
return true;
}
return false;
}
// 다음 바둑알이 범위를 벗어나거나 색이 다르다면 리턴
if (!isIn(nx, ny) || board[nx][ny] != current) return false;
cnt++;
x = nx;
y = ny;
}
}
// 범위 확인
private static boolean isIn(int nx, int ny) {
return nx >= 0 && ny >= 0 && nx < 19 && ny < 19;
}
}
'ALGORITHM > BAEKJOON' 카테고리의 다른 글
[BAEKJOON] 14620. 꽃길(JAVA) (1) | 2022.09.22 |
---|---|
[BAEKJOON] 15685. 드래곤 커브 (JAVA) (1) | 2022.09.20 |
[BAEKJOON] 14891. 톱니바퀴(JAVA) (0) | 2022.09.16 |
[BAEKJOON] 2468. 안전 영역(JAVA) (1) | 2022.09.11 |
[BAEKJOON] 3085. 사탕 게임(JAVA) (0) | 2022.09.06 |
- Total
- Today
- Yesterday