본문 바로가기

카테고리 없음

[Programmers] 혼자서 하는 틱택토 - Javascript

728x90

INDEX

    https://school.programmers.co.kr/learn/courses/30/lessons/160585#

     

    프로그래머스

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

    programmers.co.kr

     

    Solution

    머쓱이가 잘못 게임을 진행했을 경우는 다음과 같습니다.

    1) "O"를 "X"로, "X"를 "O"로 착각한다.

    2) 게임이 종료되었는데도 계속 진행한다.

     

    1번의 경우는 "X"와 "O"의 개수를 검사해 주면 됩니다.

    선공의 경우 "O"부터 놓기 때문에 "O"이 "X"와 같거나 더 많아야 하지만 2개 이상 많으면 안 됩니다.

    또한 "X"는 후공이기 때문에 "O"보다 더 많으면 안 됩니다.

     

    2번의 경우 선공 혹은 후공이 승리를 했지만 계속 진행한 경우인 만큼 이 때도 승리 조건 하에 개수를 비교해 주면 됩니다.

    따라서 주어진 board에서 "X"는 몇 번 나왔는지와 "O"는 몇 번 나왔는지 카운트를 해줍니다.

     

    let OCount = 0;
    let XCount = 0;
    
    for(let row =0; row<board.length; row++){
        for(let col =0; col<board[0].length; col++){
            if(board[row][col] === 'O'){
                OCount++;
            }else if(board[row][col]==='X'){
                XCount++;
            }
        }
    }

     

    그리고 누가 승리했는지(틱택토 완성) 검사해야 합니다. 그러기 위해선 가로행과 세로열로 비교해도 되지만 저는 숫자 배열판을 사용했습니다.

    [0, 1, 2]
    [3, 4, 5]
    [6, 7, 8]

    가로행 틱택토는 [0, 1, 2], [3, 4, 5], [6, 7, 8]이고 세로행 틱택토는 [0, 3, 6], [1, 4, 7], [2, 5, 8], 대각선은 [0, 4, 8], [2, 4, 6]입니다. 

    const rowTick = [[0,1,2],[3,4,5],[6,7,8]];
    const colTack = [[0, 3, 6], [1,4,7], [2,5,8]];
    const crossToe = [[0, 4, 8], [2,4,6]];

    이제 X와 O가 어떤 값에 들어있는지 위 반복문에서 같이 찾아줍니다.

    let OArr = [];
    let XArr = [];
    let index = 0;
    for(let row =0; row<board.length; row++){
        for(let col =0; col<board[0].length; col++){
            if(board[row][col] === 'O'){
                OCount++;
                OArr.push(index);
            }else if(board[row][col]==='X'){
                XCount++;
                XArr.push(index);
            }
            index++;
    
        }
    }

     

    board가 아래처럼 주어졌다면 OArr 에는 [0, 4], XArr 에는 [2, 8] 이 들어있습니다.

    이를 이용해서 틱택토를 완성시켰는지 검사하는 함수를 하나 만들어봅니다.

    function checkTick(arr, tick){
        for(let i=0; i<tick.length; i++){
            let tickCount = 0;
            for(let j=0; j<arr.length; j++){
                if(tick[i].includes(arr[j])) tickCount++;
            }
            if(tickCount === 3) return true;
        }
        return false;
    }

    이 함수를 사용하는 방법은 아래와 같습니다.

    const isOTick = checkTick(OArr, rowTick) || checkTick(OArr, colTack) || checkTick(OArr, crossToe);
    const isXTick = checkTick(XArr, rowTick) || checkTick(XArr, colTack) || checkTick(XArr, crossToe);

    한 행이라도 완성을 시킨다면 각 isOTickisXTick 에는 true 가 들어가고 맞지 않다면 false가 들어가겠죠.

     

    위 주어진 예시대로 라면 둘 다 false 가 들어가 있을 겁니다.

     

    이제 조건 검사를 해줍니다.

    1) "O"를 "X"로, "X"를 "O"로 착각한다.

    if(XCount>OCount) return 0; //후공이 선공보다 많이 둘 순 없습니다.
    if(OCount>XCount+1) return 0; //선공이 후공보다 두 개 더 둘 순 없습니다.

    2) 게임이 종료되었는데도 계속 진행한다.

    if(isOTick && isXTick){
        return 0; //둘다 승리할순없습니다.   
    }else if(isOTick){ //선공이 승리했는데 후공과 개수가 같을 순 없습니다.
        if(OCount=== XCount) return 0;
    }else if(isXTick){//후공이 승리했는데 선공이 더 많을순없습니다.
        if(OCount > XCount) return 0; 
    }

     

    이 문제는 이전 문제들과는 달리 얼마나 조건문을 잘 짜는지가 중요한 문제여서 신선하고 재밌게 느껴졌습니다. 테스트 문제도 50개가 넘어가서 한 두 문제씩 틀렸을 땐 멘붕에 빠지곤 했습니다. 하지만 잘 생각해 보니 결국 풀리긴 하더군요..ㅎㅎ