https://www.acmicpc.net/problem/2615
2615번: 오목
오목은 바둑판에 검은 바둑알과 흰 바둑알을 교대로 놓아서 겨루는 게임이다. 바둑판에는 19개의 가로줄과 19개의 세로줄이 그려져 있는데 가로줄은 위에서부터 아래로 1번, 2번, ... ,19번의 번호
www.acmicpc.net
풀이
바둑판의 상태를 입력받은 후, 검은색 또는 흰색이 이기는지 출력하고 가장 왼쪽에 있는 바둑알의 위치를 출력한다.
로직
1. 바둑판의 상태를 입력받는다.
2. 이중 for문을 사용하여 바둑판을 왼쪽 위부터 탐색하고, 바둑알이 놓인 위치인 경우 check 함수를 호출하여 오목이 된 경우 검은색이 이겼을 경우에는 1을, 흰색이 이겼을 경우에는 2를 출력한다. 그리고 현재 위치를 출력하고 프로그램을 종료한다.
3. 위의 이중 for문에서 프로그램이 종료되지 않은 경우는 아직 승부가 결정되지 않은 경우이므로 0을 출력한다.
boolean check(int[][] board, int color, int i, int j) : 현재 위치를 시작점으로 삼아 오목이 된 경우 true, 아니면 false 리턴
public static boolean check(int[][] board, int color, int i, int j) {
//가로 5개
boolean flag = true;
int nx, ny;
for (int r = 1; r < 5; r++) {
ny = j + r;
if (ny < 0 || ny >= 19) {
flag = false;
break;
}
else if (board[i][ny] != color) {
flag = false;
break;
}
}
if (flag) {
ny = j + 5;
if (ny >= 19 || board[i][ny] != color) {
ny = j - 1;
if (ny < 0 || board[i][ny] != color)
return true;
}
}
//세로 5개
flag = true;
for (int r = 1; r < 5; r++) {
nx = i + r;
if (nx < 0 || nx >= 19) {
flag = false;
break;
}
if (board[nx][j] != color) {
flag = false;
break;
}
}
if (flag) {
nx = i + 5;
if (nx >= 19 || board[nx][j] != color) {
nx = i - 1;
if (nx < 0 || board[nx][j] != color)
return true;
}
}
//대각선 5개(좌측 상단->우측 하단)
flag = true;
for (int r = 1; r < 5; r++) {
nx = i + r;
ny = j + r;
if (nx < 0 || nx >= 19 || ny < 0 || ny >= 19) {
flag = false;
break;
}
if (board[i+r][j+r] != color) {
flag = false;
break;
}
}
if (flag) {
nx = i + 5;
ny = j + 5;
if (nx >= 19 || ny >= 19 || board[nx][ny] != color) {
nx = i - 1;
ny = j - 1;
if (nx < 0 || ny < 0 || board[nx][ny] != color)
return true;
}
}
//대각선 5개(좌측 하단->우측 상단)
flag = true;
for (int r = 1; r < 5; r++) {
nx = i - r;
ny = j + r;
if (nx < 0 || nx >= 19 || ny < 0 || ny >= 19) {
flag = false;
break;
}
if (board[nx][ny] != color) {
flag = false;
break;
}
}
if (flag) {
nx = i - 5;
ny = j + 5;
if (nx < 0 || ny >= 19 || board[nx][ny] != color) {
nx = i + 1;
ny = j - 1;
if (nx > 19 || ny < 0 || board[nx][ny] != color)
return true;
}
}
// 오목이 되자 않는다면 false 리턴
return false;
}
가로로 5개, 세로로 5개, 대각선은 두가지 경우( 좌측 상단->우측 하단 / 좌측 하단 -> 우측 상단)를 모두 따져서 오목이 되었는지 확인한다.
주의할 점
- 여섯 알 이상이 연속적으로 놓인 경우에는 이긴 것이 아니다. 즉 같은 색의 바둑알이 연속적으로 5알이 놓이더라도, 각 경우에 대해 5알 양 끝 위치에 바둑알이 놓여있지 않거나 다른 색이거나 바둑판 범위를 벗어난 경우에만 true를 리턴한다.
- 각 경우에 대한 인덱스 체크가 까다롭다.
육목 테스트 케이스
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 1 2 0 0 2 2 2 1 0 0 0 0 0 0 0 0 0 1
1 0 1 2 0 0 0 0 1 0 0 0 0 0 0 0 0 0 2
1 0 0 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 0 0 0
1 0 1 1 0 1 1 2 1 1 1 1 1 1 1 0 0 0 0
1 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 1 0 0 0 0 2 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0
0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0
0 0 0 0 0 0 1 0 0 0 0 0 2 0 0 0 0 0 0
0 0 0 0 0 1 0 0 0 0 0 0 2 0 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 2 0
0 0 0 1 0 0 0 0 0 0 0 0 0 0 2 0 0 2 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 2 1
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 2
0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 1 2 2 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 1 2 2 2
코드
import java.io.*;
import java.util.*;
public class Main {
public static boolean check(int[][] board, int color, int i, int j) {
//가로 5개
boolean flag = true;
int nx, ny;
for (int r = 1; r < 5; r++) {
ny = j + r;
if (ny < 0 || ny >= 19) {
flag = false;
break;
}
else if (board[i][ny] != color) {
flag = false;
break;
}
}
if (flag) {
ny = j + 5;
if (ny >= 19 || board[i][ny] != color) {
ny = j - 1;
if (ny < 0 || board[i][ny] != color)
return true;
}
}
//세로 5개
flag = true;
for (int r = 1; r < 5; r++) {
nx = i + r;
if (nx < 0 || nx >= 19) {
flag = false;
break;
}
if (board[nx][j] != color) {
flag = false;
break;
}
}
if (flag) {
nx = i + 5;
if (nx >= 19 || board[nx][j] != color) {
nx = i - 1;
if (nx < 0 || board[nx][j] != color)
return true;
}
}
//대각선 5개(좌측 상단->우측 하단)
flag = true;
for (int r = 1; r < 5; r++) {
nx = i + r;
ny = j + r;
if (nx < 0 || nx >= 19 || ny < 0 || ny >= 19) {
flag = false;
break;
}
if (board[i+r][j+r] != color) {
flag = false;
break;
}
}
if (flag) {
nx = i + 5;
ny = j + 5;
if (nx >= 19 || ny >= 19 || board[nx][ny] != color) {
nx = i - 1;
ny = j - 1;
if (nx < 0 || ny < 0 || board[nx][ny] != color)
return true;
}
}
//대각선 5개(좌측 하단->우측 상단)
flag = true;
for (int r = 1; r < 5; r++) {
nx = i - r;
ny = j + r;
if (nx < 0 || nx >= 19 || ny < 0 || ny >= 19) {
flag = false;
break;
}
if (board[nx][ny] != color) {
flag = false;
break;
}
}
if (flag) {
nx = i - 5;
ny = j + 5;
if (nx < 0 || ny >= 19 || board[nx][ny] != color) {
nx = i + 1;
ny = j - 1;
if (nx > 19 || ny < 0 || board[nx][ny] != color)
return true;
}
}
// 오목이 되자 않는다면 false 리턴
return false;
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int[][] board = new int[19][19];
StringTokenizer st;
for (int i = 0; i < 19; i++) {
st = new StringTokenizer(br.readLine());
for (int j = 0; j < 19; j++) {
board[i][j] = Integer.parseInt(st.nextToken());
}
}
for (int i = 0; i < 19; i++) {
for (int j = 0; j < 19; j++) {
if (board[i][j] != 0) {
if (check(board, board[i][j], i ,j)) {
System.out.println(board[i][j]);
System.out.println((i+1) + " " + (j+1));
return;
}
}
}
}
System.out.println("0");
}
}
코드 수정
현재 위치를 시작점으로 삼아 오목이 되는지 판별하는 check 함수가 너무 길며 각 경우에 대해 로직이 중복된다. 이를 줄이기 위해 방향 배열과 반복문을 사용한다.
import java.io.*;
import java.util.*;
public class Main {
public static boolean check(int[][] board, int color, int i, int j) {
int[][] d = {{0,1}, {1,0}, {1,1}, {-1, 1}}; // 가로, 세로, 대각선 2개
for (int k = 0; k < 4; k++) { // 각 방향에 대해서
int nx = i, ny = j; // i, j에서 시작
int cnt = 1;
for (int l = 0; l < 5; l++) { // 육목이 되는지 판별하기 위해 현재 위치 다음의 5개의 바둑돌을 탐색
nx += d[k][0];
ny += d[k][1];
if (nx < 0 || nx >= 19 || ny < 0 || ny >= 19) {
break;
}
else if (board[nx][ny] != color) {
break;
}
cnt++;
}
// 오목이 된다면 반대쪽에서 육목이 되는지 판별
if (cnt == 5) {
nx = i - d[k][0];
ny = j - d[k][1];
// 바둑판의 위치를 벗어나거나, color와 다르다면 오목이 되므로 true 리턴
if (nx < 0 || nx >= 19 || ny < 0 || ny >= 19)
return true;
else if (board[nx][ny] != color) {
return true;
}
}
}
return false;
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int[][] board = new int[19][19];
StringTokenizer st;
for (int i = 0; i < 19; i++) {
st = new StringTokenizer(br.readLine());
for (int j = 0; j < 19; j++) {
board[i][j] = Integer.parseInt(st.nextToken());
}
}
for (int i = 0; i < 19; i++) {
for (int j = 0; j < 19; j++) {
if (board[i][j] != 0) {
if (check(board, board[i][j], i ,j)) {
System.out.println(board[i][j]);
System.out.println((i+1) + " " + (j+1));
return;
}
}
}
}
System.out.println("0");
}
}
'Algorithm 문제 풀이 > 백준' 카테고리의 다른 글
[백준] 9205번 : 맥주 마시면서 걸어가기 - 자바[Java] (0) | 2022.10.04 |
---|---|
[백준] 15787번 : 기차가 어둠을 헤치고 은하수를 - 자바[Java] (1) | 2022.09.30 |
[백준] 1874번 : 스택 수열 - 자바[Java] (1) | 2022.09.25 |
[백준] 1021번 : 회전하는 큐 - 자바[Java] (0) | 2022.09.24 |
[백준] 9012번 : 괄호 - 자바[Java] (1) | 2022.09.24 |