본문 바로가기
Algorithm/Baekjoon

Baekjoon 2615 오목 JAVA

by Hunveloper 2022. 1. 26.
728x90
 

2615번: 오목

오목은 바둑판에 검은 바둑알과 흰 바둑알을 교대로 놓아서 겨루는 게임이다. 바둑판에는 19개의 가로줄과 19개의 세로줄이 그려져 있는데 가로줄은 위에서부터 아래로 1번, 2번, ... ,19번의 번호

www.acmicpc.net

문제

오목은 바둑판에 검은 바둑알과 흰 바둑알을 교대로 놓아서 겨루는 게임이다. 바둑판에는 19개의 가로줄과 19개의 세로줄이 그려져 있는데 가로줄은 위에서부터 아래로 1번, 2번, ... ,19번의 번호가 붙고 세로줄은 왼쪽에서부터 오른쪽으로 1번, 2번, ... 19번의 번호가 붙는다.

위의 그림에서와 같이 같은 색의 바둑알이 연속적으로 다섯 알을 놓이면 그 색이 이기게 된다. 여기서 연속적이란 가로, 세로 또는 대각선 방향 모두를 뜻한다. 즉, 위의 그림은 검은색이 이긴 경우이다. 하지만 여섯 알 이상이 연속적으로 놓인 경우에는 이긴 것이 아니다.

입력으로 바둑판의 어떤 상태가 주어졌을 때, 검은색이 이겼는지, 흰색이 이겼는지 또는 아직 승부가 결정되지 않았는지를 판단하는 프로그램을 작성하시오. 단, 검은색과 흰색이 동시에 이기거나 검은색 또는 흰색이 두 군데 이상에서 동시에 이기는 경우는 입력으로 들어오지 않는다.

입력

19줄에 각 줄마다 19개의 숫자로 표현되는데, 검은 바둑알은 1, 흰 바둑알은 2, 알이 놓이지 않는 자리는 0으로 표시되며, 숫자는 한 칸씩 띄어서 표시된다.

출력

첫줄에 검은색이 이겼을 경우에는 1을, 흰색이 이겼을 경우에는 2를, 아직 승부가 결정되지 않았을 경우에는 0을 출력한다. 검은색 또는 흰색이 이겼을 경우에는 둘째 줄에 연속된 다섯 개의 바둑알 중에서 가장 왼쪽에 있는 바둑알(연속된 다섯 개의 바둑알이 세로로 놓인 경우, 그 중 가장 위에 있는 것)의 가로줄 번호와, 세로줄 번호를 순서대로 출력한다.

풀이

델타배열을 이용하여 좌측에서 우측방향, 위에서 밑방향으로 검사를 한다.

6목이상을 방지하기 위해서 5개를 카운팅하고 돌아와서 반대방향으로 한칸을 검사한다.

행 열기준으로 검사할때 만약에 1,1에서 6목이었는데, 2,2에서 검사하면 오목이라고 출력을 할 것이다.

이것을 방지하기 위해서 시작점에서 검사한 방향 반대로 한번 검사하면 오목이상인지 아닌지 방지할 수 있다.

코드
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class Main {

	public static void main(String[] args) throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		boolean chk=true;
		int [][] map = new int [19][19];
		int [] dx = new int[] {1,0,-1,1}, dy=new int[] {1,1,1,0};		// 4방 탐색 (출력의 기준점은 1.좌측 2.상단 순서이므로 우에서 좌로 오는것은 생각 X)
		for(int i=0;i<19;i++) {			// 입력
			StringTokenizer st = new StringTokenizer(br.readLine());
			for(int j=0;j<19;j++)
				map[i][j]=Integer.parseInt(st.nextToken());
		}
		for(int i=0;i<19;i++)			// 맵 전체 확인
		{
			for(int j=0;j<19;j++) 
			{
				int prev=-1;
				if(map[i][j]==1 || map[i][j]==2) {	// 흑 or 백 확인후 선택
					prev=map[i][j];
					for(int k=0;k<4;k++) {			// a, b케이스는 4가지임
						int cnt=1;
						int ii=dx[k], jj=dy[k];		// 변동되는 좌표
						if(i+ii>=19 || i+ii<0 || j+jj>=19 || j+jj<0)
							continue;
						while(map[i+ii][j+jj]==prev) {	// 연속되는 자리가 시작 위치랑 같으면 cnt 증가
							cnt++;
							ii+=dx[k];
							jj+=dy[k];
							if(cnt>5)
								break;
							if(i+ii>=19 || i+ii<0 || j+jj>=19 || j+jj<0)
								break;
						}
						if(i-dx[k]>=0 && j-dy[k]>=0 && i-dx[k]<19 && j-dy[k]<19)	
							if(map[i-dx[k]][j-dy[k]]==prev)	// 5번을 다하고 돌아왔을때 반대로 돌이 있는경우 6이된다. 이런 경우 이미 지나온 경로이므로 거짓으로 판단. 종료시킴 
								continue;
						if(cnt==5) {		// 6목의 경우는 31번 줄에서 판단 했으므로 5개의 경우 5목으로 판단함.
							System.out.println(prev);
							System.out.println(String.valueOf(i+1)+" "+String.valueOf(j+1));
							chk=false;
							return ;
						}
					}
				}			
			}
		}
		if(chk)
			System.out.println(0);
	}
}
728x90
728x90

댓글