Algorithm/Programmers

[Programmers] 혼자서 하는 틱택토 / ⭕

cks._.hong 2024. 7. 11. 18:59
 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

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. 구현 로직

  1. 게임판에서 선공과 후공의 개수를 Count
  2. 선공이 후공보다 2개 이상일 수 있는 경우와 선공보다 후공이 더 많을 수 없으니 return 0
  3. 각 행, 열, 대각선에서 틱택토 게임의 정답을 만족하는 조건을 Count
  4. 선공 또는 후공이 각 행, 열, 대각선에서 2개 이상의 정답이 존재할 수 없으니 return 0
  5. 선공이 이겼는데 후공이 계속 공격할 수 없으니 행, 열, 대각선에서 정답을 만족하는 조건이 있다면 선공 = 후공 일 때 return 0 (<는 위에서 필터됨)
  6. 후공이 이겼는데 선공이 게속 공격할 수 없으므로 선공 > 후공 일 때 return 0
  7. 이 외에 경우는 모두 진행 가능한 상황으로 정답 추출

 

3. 유의할 점

  • 선공이 이겼는데 선공이 공격하는 경우를 생각 못 해서 테스트 케이스 일부를 틀려서 예외 상황을 잘 생각해야 할 거 같다.