https://school.programmers.co.kr/learn/courses/30/lessons/160585
단순 구현
단순 구현문제이다.
특별한 알고리즘을 요구하지는 않지만, 조건을 잘 이해하고 빼먹지 말아야 한다.
종료 조건을 바탕으로 어떤 케이스가 실수를 한 것인지 살펴보자.
조건1을 살펴보자.
한 번씩 순서를 번갈아가며 표시를 한다.
따라서 O의 갯수와 X의 갯수는 같거나 O가 1개 더 많아야 한다
조건2의 경우를 살펴보자.
만약 O가 승리하는 경우라면,
O가 반드시 1개 더 표시한 상태에서 종료된다. ( O가 먼저 그리기 시작하므로 )
반대로 X가 승리하는 경우라면, O와 X의 표시한 갯수는 같아야 한다.
그리고 마지막으로 둘 다 승리하는 경우는 없다.
( 한명이 승리하면 바로 종료되어야 하기때문 )
즉 불가능한 경우를 정리하자면 아래와 같다.
1. 순서를 어긋나게 표시
2. 종료되었음에도 계속 진행된 경우
a. 둘 다 승리하는 경우
b. "O가 승리한다면, 반드시 하나 더 표시" 를 미 충족
c. "X가 승리한다면, 반드시 동일 수 만큼 표시" 를 미 충족
import java.util.Arrays;
class Solution {
int SIZE = 3;
char[][] arr = new char[SIZE][SIZE];
public int solution(String[] board) {
for (int i = 0; i < SIZE; ++i)
arr[i] = board[i].toCharArray();
// Step1. 순서가 어긋난 경우.
int numP1 = getCount('O');
int numP2 = getCount('X');
if (!((numP1 == numP2) || (numP1 == numP2 + 1)))
return 0;
// Step2. 종료되었음에도 계속 진행된 경우
boolean p1CanWin = canWin('O');
boolean p2CanWin = canWin('X');
// Step2-1. 둘 다 승리할 수 있게 두는 경우는 나오지 않는다.
if (p1CanWin && p2CanWin)
return 0;
// Step2-2. p1가 승리한다면 반드시 하나 더 표시했다.
if (p1CanWin && !(numP1 == numP2 + 1))
return 0;
// Step2-3. p2가 승리한다면 반드시 같은 수를 표시했다.
if (p2CanWin && !(numP1 == numP2))
return 0;
return 1;
}
private boolean canWin(char c) {
for (int i = 0; i < SIZE; ++i) {
// 가로 체크
if ((arr[i][0] == arr[i][1]) && (arr[i][0] == arr[i][2]) && (arr[i][0] == c))
return true;
// 세로 체크
if ((arr[0][i] == arr[1][i]) && (arr[0][i] == arr[2][i]) && (arr[0][i] == c))
return true;
}
// 좌상-우하 대각
if ((arr[0][0] == arr[1][1]) && (arr[0][0] == arr[2][2]) && (arr[0][0] == c))
return true;
// 좌하-우상 대각
if ((arr[0][2] == arr[1][1]) && (arr[0][2] == arr[2][0]) && (arr[0][2] == c))
return true;
return false;
}
public int getCount(char target) {
return (int)Arrays.stream(arr)
.flatMapToInt(chars -> new String(chars).chars())
.filter(c -> c == target)
.count();
}
}