1. 제출 코드 (1시간 23분 32초 / 구현)
import java.util.*;
class Solution {
static ArrayList<Character>[] map;
public int solution(String[] board) {
int answer = 1;
int p1 = 0;
int p2 = 0;
map = new ArrayList[3];
for(int i = 0; i < 3; i++) {
map[i] = new ArrayList<>();
for(int j = 0; j < 3; j++) {
if(board[i].charAt(j) == 'O') {
p1++;
} else if(board[i].charAt(j) == 'X'){
p2++;
}
map[i].add(board[i].charAt(j));
}
}
/*
1. 선공이 후공보다 2개 이상일 수 없음
2. 선공보다 후공이 더 많을 수 없음
*/
if(p1 - p2 >= 2 || p1 - p2 < 0) return 0;
int[] rowCnt = rowCount();
int[] colCnt = colCount();
int[] crossCnt = crossCount();
// 3. 각 행, 열, 대각선에서는 2개 이상의 승리 조건을 만들 수 없음
if(rowCnt[0] >= 2 || rowCnt[1] >= 2 || colCnt[0] >= 2 || colCnt[1] >= 2 || crossCnt[0] >= 2 || crossCnt[1] >= 2) {
return 0;
}
// 4. 선공이 이겼는데 후공이 계속 공격할 수 없음
if(rowCnt[0] == 1 || colCnt[0] == 1 || crossCnt[0] == 1) {
if(p1 == p2) return 0;
}
// 5. 후공이 이겼는데 선공이 계속 공격할 수 없음
if(rowCnt[1] == 1 || colCnt[1] == 1 || crossCnt[1] == 1) {
if(p1 > p2) return 0;
}
return answer;
}
static int[] rowCount() {
int o_cnt = 0;
int x_cnt = 0;
for(int i = 0; i < 3; i++) {
boolean isValid = true;
char temp = map[i].get(0);
if(temp == '.') continue;
for(int j = 1; j < 3; j++) {
if(temp == 'O' && map[i].get(j) != 'O') {
isValid = false;
break;
} else if(temp == 'X' && map[i].get(j) != 'X'){
isValid = false;
break;
}
}
if(isValid) {
if(temp == 'O') o_cnt++;
else x_cnt++;
}
}
return new int[] {o_cnt, x_cnt};
}
static int[] crossCount() {
int o_cnt = 0;
int x_cnt = 0;
char leftTemp = map[0].get(0);
if(leftTemp != '.'){
boolean leftValid = true;
for(int i = 1; i < 3; i++) {
if(leftTemp == 'O' && map[i].get(i) != 'O') {
leftValid = false;
break;
} else if(leftTemp == 'X' && map[i].get(i) != 'X'){
leftValid = false;
break;
}
}
if(leftValid) {
if(leftTemp == 'O') o_cnt++;
else x_cnt++;
}
}
char rightTemp = map[0].get(2);
if(rightTemp != '.') {
boolean rightValid = true;
for(int i = 1; i < 3; i++) {
if(rightTemp == 'O' && map[i].get(2 - i) != 'O') {
rightValid = false;
break;
} else if(rightTemp == 'X' && map[i].get(2 - i) != 'X'){
rightValid = false;
break;
}
}
if(rightValid) {
if(rightTemp == 'O') o_cnt++;
else x_cnt++;
}
}
return new int[] {o_cnt, x_cnt};
}
static int[] colCount() {
int o_cnt = 0;
int x_cnt = 0;
for(int i = 0; i < 3; i++) {
boolean isValid = true;
char temp = map[0].get(i);
if(temp == '.') continue;
for(int j = 1; j < 3; j++) {
if(temp == 'O' && map[j].get(i) != 'O') {
isValid = false;
break;
} else if(temp == 'X' && map[j].get(i) != 'X'){
isValid = false;
break;
}
}
if(isValid) {
if(temp == 'O') o_cnt++;
else x_cnt++;
}
}
return new int[] {o_cnt, x_cnt};
}
}
2. 구현 로직
- 게임판에서 선공과 후공의 개수를 Count
- 선공이 후공보다 2개 이상일 수 있는 경우와 선공보다 후공이 더 많을 수 없으니 return 0
- 각 행, 열, 대각선에서 틱택토 게임의 정답을 만족하는 조건을 Count
- 선공 또는 후공이 각 행, 열, 대각선에서 2개 이상의 정답이 존재할 수 없으니 return 0
- 선공이 이겼는데 후공이 계속 공격할 수 없으니 행, 열, 대각선에서 정답을 만족하는 조건이 있다면 선공 = 후공 일 때 return 0 (<는 위에서 필터됨)
- 후공이 이겼는데 선공이 게속 공격할 수 없으므로 선공 > 후공 일 때 return 0
- 이 외에 경우는 모두 진행 가능한 상황으로 정답 추출
3. 유의할 점
- 선공이 이겼는데 선공이 공격하는 경우를 생각 못 해서 테스트 케이스 일부를 틀려서 예외 상황을 잘 생각해야 할 거 같다.