[programmers/js] 혼자서 하는 틱택토

승민·2025년 3월 7일

알고리즘

목록 보기
141/171

혼자서 하는 틱택토

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

문제 설명

할 일이 없어 한가한 머쓱이는 두 사람이 하는 게임인 틱택토를 다음과 같이 혼자서 하려고 합니다.

규칙

  • 혼자서 선공과 후공을 둘 다 맡는다.
  • 틱택토 게임을 시작한 후 "O"와 "X"를 혼자서 번갈아 가면서 표시를 하면서 진행한다.

틱택토는 단순한 규칙으로 게임이 금방 끝나기에 머쓱이는 한 게임이 종료되면 다시 3x3 빈칸을 그린 뒤 다시 게임을 반복했습니다. 그렇게 틱택토 수 십 판을 했더니 머쓱이는 게임 도중에 다음과 같이 규칙을 어기는 실수를 했을 수도 있습니다.

  • "O"를 표시할 차례인데 "X"를 표시하거나 반대로 "X"를 표시할 차례인데 "O"를 표시한다.
  • 선공이나 후공이 승리해서 게임이 종료되었음에도 그 게임을 진행한다.

게임 도중 게임판을 본 어느 순간 머쓱이는 본인이 실수를 했는지 의문이 생겼습니다. 혼자서 틱택토를 했기에 게임하는 과정을 지켜본 사람이 없어 이를 알 수는 없습니다. 그러나 게임판만 봤을 때 실제로 틱택토 규칙을 지켜서 진행했을 때 나올 수 있는 상황인지는 판단할 수 있을 것 같고 문제가 없다면 게임을 이어서 하려고 합니다.

머쓱이가 혼자서 게임을 진행하다 의문이 생긴 틱택토 게임판의 정보를 담고 있는 문자열 배열 board가 매개변수로 주어질 때, 이 게임판이 규칙을 지켜서 틱택토를 진행했을 때 나올 수 있는 게임 상황이면 1을 아니라면 0을 return 하는 solution 함수를 작성해 주세요.

풀이

틱택토의 배열을 3*3으로 고정되어 완탐을 사용해 풀면됩니다.
설명을 읽고 조건을 분류하면

  1. O 갯수가 X 갯수와 같을때, O 빙고가 아니라면 성공
  2. O 갯수가 X 갯수보다 1개 많을때, X 빙고가 아니라면 성공
  3. 아니면 다 실패

위 3가지 조건으로 분류할 수 있습니다.

// 완탐
function solution(board) {
    const text = {
        "O": [],
        "X": [],
        ".": [],
    };

    const bingo = [
        [[0, 0], [1, 0], [2, 0]],
        [[0, 1], [1, 1], [2, 1]],
        [[0, 2], [1, 2], [2, 2]],
        [[0, 0], [1, 1], [2, 2]],
        [[2, 0], [1, 1], [0, 2]],
        [[0, 0], [0, 1], [0, 2]],
        [[1, 0], [1, 1], [1, 2]],
        [[2, 0], [2, 1], [2, 2]],
    ];
    
    board.forEach((row, ri) => {
        row.split('').map((ch, ci) => {
            // [ci, ri]
            text[ch].push([ci, ri])
        })
    })
    
    const oCount = text["O"].length;
    const xCount = text["X"].length;
    
    // 1. O 갯수가 X 갯수와 같을때, O 빙고가 아니라면 성공
    if (oCount === xCount) {
        for (let i = 0; i < bingo.length; i++) {
            const arr = bingo[i];
            let cnt = 0;                
            text["O"].forEach(([x, y]) => {
                arr.forEach(([x1, y1]) => {
                    if ((x1 === x && y1 === y)) cnt += 1;
                })  
            })
            if (cnt === 3) return 0;
        }
    } else if (oCount === xCount + 1) {
        // 2. O 갯수가 X 갯수보다 1개 많을때, X 빙고가 아니라면 성공
        for (let i = 0; i < bingo.length; i++) {
            const arr = bingo[i];
            let cnt = 0;                
            text["X"].forEach(([x, y]) => {
                arr.forEach(([x1, y1]) => {
                    if ((x1 === x && y1 === y)) cnt += 1;
                })  
            })
            if (cnt === 3) return 0;
        }
    } else return 0;
    
    return 1;
}

다른 사람 풀이

bingo 변수를 반복문을 돌면서 확인하는게 아닌 배열을 1차원으로 변경해 문자열로 확인

function solution(board) {
    let b = board.reduce((a,c)=>[...a,...c], [])
    let finishO = false
    let finishX = false
    let oCount = 0
    let xCount = 0
    if (`${b[0]}${b[1]}${b[2]}` == 'OOO' ||
        `${b[3]}${b[4]}${b[5]}` == 'OOO' ||
        `${b[6]}${b[7]}${b[8]}` == 'OOO' ||
        `${b[0]}${b[3]}${b[6]}` == 'OOO' ||
        `${b[1]}${b[4]}${b[7]}` == 'OOO' ||
        `${b[2]}${b[5]}${b[8]}` == 'OOO' ||
        `${b[0]}${b[4]}${b[8]}` == 'OOO' ||
        `${b[2]}${b[4]}${b[6]}` == 'OOO'
       ) finishO = true
    if (`${b[0]}${b[1]}${b[2]}` == 'XXX' ||
        `${b[3]}${b[4]}${b[5]}` == 'XXX' ||
        `${b[6]}${b[7]}${b[8]}` == 'XXX' ||
        `${b[0]}${b[3]}${b[6]}` == 'XXX' ||
        `${b[1]}${b[4]}${b[7]}` == 'XXX' ||
        `${b[2]}${b[5]}${b[8]}` == 'XXX' ||
        `${b[0]}${b[4]}${b[8]}` == 'XXX' ||
        `${b[2]}${b[4]}${b[6]}` == 'XXX'
       ) finishX = true
    for(let i=0;i<b.length;i++){
        if (b[i]=='O') oCount++
        else if (b[i]=='X') xCount++
    }
    if (oCount == xCount + 1 && finishX == false) return 1
    else if (oCount == xCount && finishO == false) return 1
    else return 0
}

0개의 댓글