알고리즘

프로그래머스 - 혼자하는 틱택토

hwigaeng 2025. 1. 22. 17:12

문제 

틱택토를 진행한 보드판이 주어질 때 해당 보드 판이 정상적으로 진행된 틱택토인지 확인하는 문제이다.

내 풀이

틱택토는 O(선공)와 X(후공)가 번갈아가며 진행하는 게임이다. 각 플레이어는 한 번씩 번갈아 두어야 하므로, 게임이 정상적으로 진행되려면 다음 규칙들이 지켜져야 한다:

  • O는 반드시 첫 번째로 둬야 한다
  • O와 X는 반드시 번갈아 두어야 한다
  • 한 플레이어가 승리하면 게임이 즉시 종료되어야 한다

이러한 규칙들을 바탕으로 정상적이지 않은 틱택토의 경우를 찾아보면 

  1. 선공(O)과 후공(X)의 차이가 2 이상이거나 후공이 선공보다 많이 진행한 경우
    • O와 X는 번갈아 두므로 X의 개수는 절대 O의 개수보다 많을 수 없다
    • O와 X의 개수 차이는 최대 1까지만 가능하다 예시: 'XXO..' (X가 O보다 많음 → 불가능)
  2. 선공(O)이 승리하였는데 후공과 선공의 진행 수가 같은 경우
    • O가 승리했다면 마지막으로 O를 둔 순간에 승리한 것이므로
    • O의 개수는 반드시 X보다 1개 많아야 한다 예시: 'OOO/XXX/..' (O가 이겼는데 X도 3번 둠 → 불가능)
  3. 후공(X)이 승리하였는데 선공의 수가 후공보다 많은 경우
    • X가 승리했다면 마지막으로 X를 둔 순간에 승리한 것이므로
    • O와 X의 개수는 반드시 같아야 한다 예시: 'XXX/OO,/O.O' (X가 이겼는데 O를 더 둠 → 불가능)

이를 확인하기 위해서는 두 가지를 체크해야 한다:

  1. O와 X의 개수를 세어 올바른 순서로 진행되었는지 확인
  2. 승리 조건을 확인하여 게임이 정상적으로 종료되었는지 확인

선공과 후공의 진행횟수를 확인 하는 코드

  • X의 개수(후공)를 세어 xNum에 저장
  • O의 개수(선공)를 세어 oNum에 저장

이 값들을 통해 게임이 순서대로 진행되었는지 확인 가능해진다.

boardArr.forEach((row)=>{
    row.forEach((space)=> {
        if(space === 'X'){
            xNum ++;
        }
        if(space === "O"){
            oNum++;
        }
    })
})

게임이 끝났는지 확인 하는 함수

특정 플레이어(O 또는 X)가 승리했는지 확인하는 함수이다.

  • 가로 방향: 한 행의 모든 칸이 같은 모양인지 확인
  • 세로 방향: 한 열의 모든 칸이 같은 모양인지 확인
  • 대각선 방향: 왼쪽 위에서 오른쪽 아래 방향과 오른쪽 위에서 왼쪽 아래 방향을 확인
  • 하나라도 조건을 만족하면 해당 플레이어가 승리한 것으로 판단
const isFinish = (shape) => {
    for (let i = 0; i < boardLength; i++) {
        if (boardArr[i].every(row => row === shape)) return true; // 행 검사
        if (boardArr.every(col => col[i] === shape)) return true; // 열 검사
    }
    //대각선 검사
    if(boardArr[0][0] === shape && boardArr[1][1] === shape && boardArr[2][2] == shape) return true
    if(boardArr[0][2] === shape && boardArr[1][1] === shape && boardArr[2][0] == shape) return true
    return false;
}

전체코드

function solution(board) {
    let xNum = 0; // 후공 횟수
    let oNum = 0; // 선공 횟수
    const boardArr = board.map((row)=> row.split(''));
    const boardLength = 3;
    const isFinish = (shape) => {
        for (let i = 0; i < boardLength; i++) {
            if (boardArr[i].every(row => row === shape)) return true; // 행 검사
            if (boardArr.every(col => col[i] === shape)) return true; // 열 검사
        }
        //대각선 검사
        if(boardArr[0][0] === shape && boardArr[1][1] === shape && boardArr[2][2] == shape) return true
        if(boardArr[0][2] === shape && boardArr[1][1] === shape && boardArr[2][0] == shape) return true
        return false;
    }
    boardArr.forEach((row)=>{
        row.forEach((space)=> {
            if(space === 'X'){
                xNum ++;
            }
            if(space === "O"){
                oNum++;
            }
        })
    })
    
    const diff = Math.abs(oNum - xNum);

    if(diff >= 2 || xNum > oNum) {
        return 0;
    }
    
    if(diff === 0 && isFinish('O')){
        return 0;
    }
    
    if(oNum > xNum && isFinish('X')){
        return 0;
    }
    
    return 1;
}

 

 출처 : 프로그래머스

문제링크 : https://school.programmers.co.kr/learn/courses/30/lessons/160585

 

프로그래머스

SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프

programmers.co.kr

'알고리즘' 카테고리의 다른 글

프로그래머스 - 숫자 블록  (2) 2025.01.31
프로그래머스 - 혼자 놀기의 달인  (0) 2025.01.31
프로그래머스 - 리코쳇로봇  (0) 2025.01.20
프로그래머스 N-Queen  (2) 2025.01.18
프로그래머스 - 디펜스게임  (1) 2025.01.13