1. 문제 정의
3x3의 빙고게임과 동일하다. 3x3의 테이블에 O 또는 X를 순서대로 표시하면서 먼저 빙고를 만드는 쪽이 승리하는 게임이다. 그러나 이 문제에서는 제일 마지막 상황에서의 3x3 테이블의 상태를 보여주고, 이것이 정상적인 게임인가, 아니면 비정상적인 게임인가를 찾아내는 게임이다. (O가 선공이고 X가 후공인데 O의 갯수는 2개 X의 갯수는 3개라면 비정상적인 게임)
2. 내가 한 시도
3x3의 매우 적은 경우의 수를 가지고 있는 빙고게임에도 불구하고, 경우의 수를 공통화 시켜서 짧은 코드를 짜려고 시도하다가 많은 삽질을 경험했다.
그래서 결국에는 3x3에서 나올 수 있는 비정상 게임의 경우의 수를 걸러내는 식으로 진행했다.
3. 코드
import java.util.HashMap;
import java.util.Map;
/**
* 프로그래머스 LV2
* 혼자서하는틱택토
* 접근 방법: 정상적이지 않은 게임의 조건을 생각해내는 것이 포인트였으나, 각각의 경우의 수를 생각하기가 힘들었음.
* 최대한 쪼개서 정상적이지 않은 경우를 걸러내는 식으로 구현
*/
public class Solution {
public int solution(String[] board) {
int oSum = 0; // 'O'갯수
int xSum = 0; // 'X'갯수
/*
* O빙고와 X빙고가 공존할 때 쓰기 위한 맵
*/
Map<Character, Character> map = new HashMap<>();
map.put('O', 'X');
map.put('X', 'O');
/*
* 이차원 배열로 변환
*/
char[][] game = new char[3][3];
/*
* 이차원 배열에 데이터를 넣고, O의 갯수와 X의 갯수를 구함
*/
for (int i = 0; i < board.length; i++) {
game[i] = board[i].toCharArray();
for (int j = 0; j < game[i].length; j++) {
char c = game[i][j];
if (c == 'O') oSum++;
if (c == 'X') xSum++;
}
}
// 가로 세로 빙고일 경우 o,x 모두 3개일 경우 체크, o,x 갯수 체크
// 1. o보다 x가 많을경우
// 2. o가 x보다 2 이상 많을 경우
// 3. o가 이겼을 경우 x는 o-1, x가 이겼을 경우 o=x.
for (int i = 0; i < 3; i++) {
// 가로
if (game[i][0] == game[i][1] && game[i][1] == game[i][2] && game[i][0] != '.') {
Character character = map.get(game[i][0]);
/*
* 0,X 빙고 공존하는지 확인
*/
for (int j = i + 1; j < 3; j++) {
if (game[j][0] == character && game[j][1] == character && game[j][2] == character) {
return 0;
}
}
/*
* 0로 끝났을 때
*/
if (game[i][0] == 'O') {
if (oSum - xSum == 1) {
return 1;
}
return 0;
}
/*
* X로 끝났을 때
*/
if (game[i][0] == 'X') {
if (oSum - xSum == 0) {
return 1;
}
return 0;
}
}
// 세로
if (game[0][i] == game[1][i] && game[1][i] == game[2][i] && game[0][i] != '.') {
Character character = map.get(game[0][i]);
/*
* O,X 공존하는지 확인
*/
for (int j = i + 1; j < 3; j++) {
if (game[0][j] == character && game[1][j] == character && game[2][j] == character) {
return 0;
}
}
/*
* O로 끝났을 때
*/
if (game[0][i] == 'O') {
if (oSum - xSum == 1) {
return 1;
}
return 0;
}
/*
* X로 끝났을 때
*/
if (game[0][i] == 'X') {
if (oSum - xSum == 0) {
return 1;
}
return 0;
}
}
}
// 빙고가 없는 경우 또는 대각선 빙고일 경우 o,x 갯수만 확인하면 된다.
// 1. o로 끝났을 경우 x는 o-1, x가 빙고일 경우 o=x.
// 2. o가 x보다 2이상 큰경우
// 3. x가 o보다 큰 경우.
/*
* 왼쪽대각선
*/
if (game[0][0] == game[1][1] && game[1][1] == game[2][2] && game[0][0] != '.') {
/*
* O,X 갯수확인
*/
if (game[0][0] == 'O') {
if (oSum == xSum + 1) {
return 1;
}
return 0;
}
if (oSum == xSum) {
return 1;
}
return 0;
}
/*
* 오른쪽 대각선
*/
if (game[2][0] == game[1][1] && game[1][1] == game[0][2] && game[2][0] != '.') {
/*
* O,X 갯수확인
*/
if (game[2][0] == 'O') {
if (oSum == xSum + 1) {
return 1;
}
return 0;
}
if (oSum == xSum) {
return 1;
}
return 0;
}
// 빙고가 없는 경우
if (oSum == xSum || oSum == xSum + 1) {
return 1;
}
return 0;
}
}
4. 회고
3x3 빙고 게임에서 비정상적인 게임의 경우의수를 찾아내는 것이 핵심이었던 것 같다. 경우의 수는 많지 않았지만, 이 경우의 수를 찾아내서 걸러내는 로직을 작성하는 것에 조금 시간이 들었던 것 같다.
복잡한 문제나 경우의 수와 같은 문제를 풀 경우에는 노트에 문제를 작게작게 쪼개서 정리하는 습관을 들이면 좋을 것 같다. 아직 문제를 작게 작게 쪼개어 생각하는 습관과 그것을 메모로 풀어내서 정리하는 능력이 부족 한 것 같다.
참조
https://school.programmers.co.kr/learn/courses/30/lessons/160585
'프로그래밍 > 알고리즘 문제풀이' 카테고리의 다른 글
[pg] 프로그래머스 미로탈출 (0) | 2023.09.09 |
---|---|
[pg] 프로그래머스 당구연습 (1) | 2023.09.07 |
[pg] 프로그래머스 리코챗 로봇 (0) | 2023.09.06 |
[pg] 프로그래머스 광물캐기 (0) | 2023.09.05 |
[pg] 프로그래머스 과제 진행하기 (0) | 2023.08.26 |