Koala - 9기/기초 알고리즘 스터디

[ 백준 / C++] 16955번 : 오목, 이길 수 있을까?

정찬영 2023. 2. 9. 14:28

https://www.acmicpc.net/problem/16955

 

16955번: 오목, 이길 수 있을까?

구사과와 큐브러버는 10×10 크기의 바둑판에서 오목을 하고 있다. 턴은 구사과가 먼저 갖는다. 바둑판의 상태가 주어진다. 구사과가 턴을 한 번 더 가졌을 때, 이길 수 있는지 구하는 프로그램을

www.acmicpc.net

 

문제

구사과와 큐브러버는 10×10 크기의 바둑판에서 오목을 하고 있다. 턴은 구사과가 먼저 갖는다. 바둑판의 상태가 주어진다. 구사과가 턴을 한 번 더 가졌을 때, 이길 수 있는지 구하는 프로그램을 작성하시오.

오목에서 승리했다는 것은 자신의 돌이 5개 이상 연속한다는 것이다. 연속은 가로, 세로, 대각선 방향 모두 가능하다.

 

입력

총 10개의 줄에 바둑판의 상태가 주어진다. '.'는 빈 칸, 'X'는 구사과의 돌, 'O'는 큐브러버의 돌이다.

입력으로 주어지는 바둑판에서 구사과의 돌의 개수와 큐브러버의 돌의 개수는 항상 일치하며, 아직 승자가 정해지지 않은 상태만 입력으로 주어진다.

 

출력

구사과가 턴을 한 번 가져서 이길 수 있으면 1, 없으면 0을 출력한다.

 

문제 설명

10*10 사이즈의 오목경기가 진행중이던 바둑판이 주어지고, 그 바둑판에 구사과가 한 수를 두었을 때 승리할 수 있을지 출력하는 문제입니다.

 

코드

 

#include <iostream>
#include <string>
#include <algorithm>
#include <vector>

using namespace std;

int width_check(string s[10]);
int length_check(string s[10]);
int diagonal_check(string s[10]);


int main() {
	string board[10];
	string s;
	int q, output = 0;

	for (q = 0; q < 10; q++) {
		cin >> board[q];
	}

	output += width_check(board);
	output += length_check(board);
	output += diagonal_check(board);

	if (output > 0) {
		cout << "1";
	}
	else {
		cout << "0";
	}


	return 0;
}


int width_check(string s[10]) {
	int i, j, cnt = 0, ocnt = 0;
	for (i = 0; i < 10; i++) {
		for (int k = 0; k <= 5; k++) {
			cnt = 0;
			ocnt = 0;
			for (j = 0; j < 5; j++) {
				if (s[i][j + k] == 'X') {
					cnt++;
				}
				else if (s[i][j + k] == 'O') {
					ocnt++;
				}
			}
			if (cnt >= 4 && ocnt == 0) {
				return 1;
			}
		}
	}
	return 0;
}


int length_check(string s[10]) {
	int i, j, cnt = 0, ocnt = 0;
	for (i = 0; i < 10; i++) {
		for (int k = 0; k <= 5; k++) {
			cnt = 0;
			ocnt = 0;
			for (j = 0; j < 5; j++) {
				if (s[j + k][i] == 'X') {
					cnt++;
				}
				else if (s[j + k][i] == 'O') {
					ocnt++;
				}
			}
			if (cnt >= 4 && ocnt == 0) {
				return 1;
			}
		}
	}
	return 0;
}


int diagonal_check(string s[10]) {
	int i, j, cnt = 0, ocnt = 0;

	for (i = 0; i <= 5; i++) {
		for (j = 0; j <= 5; j++) {
			cnt = 0;
			ocnt = 0;
			for (int k = 0; k < 5; k++) {
				if (s[i + k][j + k] == 'X') {
					cnt++;
				}
				else if (s[i + k][j + k] == 'O') {
					ocnt++;
				}
			}
			if (cnt >= 4 && ocnt == 0) {
				return 1;
			}
		}
	}

	for (i = 0; i <= 5; i++) {
		for (j = 0; j <= 5; j++) {
			cnt = 0;
			ocnt = 0;
			for (int k = 0; k < 5; k++) {
				if (s[9 - (i + k)][j + k] == 'X') {
					cnt++;
				}
				else if (s[9 - (i + k)][j + k] == 'O') {
					ocnt++;
				}
			}
			if (cnt >= 4 && ocnt == 0) {
				return 1;
			}
		}
	}

	return 0;
}

 

코드 설명

10*10 사이즈의 바둑판을 입력받습니다. 그리고 저는 이 바둑판을 검사하기 위해서, 가로줄을 검사하는 함수와 세로줄을 검사하는 함수, 그리고 대각선의 경우를 검사하는 함수로, 세 함수를 만들었습니다.

가로줄을 검사하는 함수는 입력받은 바둑판에서, 5개의 바둑돌을 검사하도록 하여 모든 바둑판을 검사하고, 여기서 'X'가 4개 이상이며 'O'가 없다면 1을 반환하게 하여 결과값을 출력할 수 있게 했습니다.

세로줄을 검사하는 함수의 경우에도 마찬가지로, 모든 경우의 수를 검사하여 결과값을 출력할 수 있게 했습니다.

대각선을 검사하는 함수의 경우에는 위의 두 함수와 비슷하지만, 대각선이 두 가지의 모양으로 만들어질 수 있기 때문에, 두 가지의 대각선의 경우를 검사하여 결과값을 출력할 수 있게 했습니다.

최종적으로 main함수에서 구사과('X')가 이기는 경우가 존재하면 '1'을, 존재하지 않으면 '0'을 출력하게 하였습니다.