Software Engineering

[Python 문제 풀이] 프로그래머스 '혼자서 하는 틱택토'

머니기어 2023. 3. 12. 20:10
반응형

프로그래머스 Lv.2 '혼자서 하는 틱택토' 파이썬 코드 및 풀이

 

조건파악

3x3 틱택토 게임인데 특별히 이 문제에서는 특정시점의 게임판만 보고 문제를 해결한다.
 
규칙대로 진행되지 않기 때문에 생각보다 논리력이 요구되는 문제인 것 같다.
 
3x3이기 때문에 코드 복잡도 측면에서 제한되는 부분은 딱히 없어 보인다.
 

접근

규칙대로 진행되지 않았다고 단정할 수 있는 몇 가지 케이스들이 있을 것이다. 그리고 이 문제는 해당 케이스들을 빠짐없이 확인하는 부분을 제대로 구현했느냐가 관건이다.
 
중간과정을 생략하더라도 반드시 지켜져야 하는 규칙과 그에 따른 반례를 다음과 같이 정리해보았다.
 
선공 후공 번갈아가며 진행되어야 하기 때문에 'O'의 개수는 'X'의 개수와 같거나 한 개 많아야 한다.
 
1. 순서를 지키지 않은 경우
NOT ( 1 >= num_o - num_x >= 0 )
 
O또는 X의 빙고가 만들어졌을 경우 그 즉시 게임 종료이다.
 
따라서, 한쪽이 승리할경우 상대쪽 심볼의 개수는 정해지게 된다.
 
2O가 승리했는데 게임을 지속한 경우
bingos_o > 0 and num_o != num_x + 1
 
X의 승리일 경우 X의 개수는 O의 개수와 같아야 한다.
 
3X가 승리했는데 게임을 지속한 경우
bingos_x > 0 and num_o != num_x
 
4둘 중 한 쪽이 이미 빙고를 만들었는데 다른 한쪽에서 빙고를 또 만든 경우
bingos_o > 0 and bingos_x > 0
 
X의 빙고가 2개 이상이면 순서를 지키지 않을 수 밖에 없기 때문에 1번 조건에서 확인된다. O의 빙고가 3개 이상이 경우도 마찬가지이다.
 
다만 O로 이루어진 빙고가 2일 때는 O가 선공이라는 특징 때문에 생기는 정상적인 사례가 있다.
OXO     OXO
X   X -> XOX
OXO     OXO
위와 같이 선공인 O가 마지막 9번째 차례에 빙고 2개를 동시에 만드는 케이스가 있으나 이 케이스가 아니면 오류로 보면 된다.
 
5. O로 이루어진 빙고가 2개일 때 칸의 개수를 5개가 아닌 6개로, 즉 따로 떨어진 빙고를 만든 케이스
bingos_o == 2 and num_o != 5
 
 
의사코드

O의 개수와 X의 개수를 모두 센다.
O와 X로 만들어진 빙고의 수를 각각 센다.
위 다섯 가지 케이스에 해당하면 0(오류)를 반환.
그렇지 않으면 1을 반환

 

구현

def solution(board):
    answer = -1
    normal = 1
    error = 0
    num_o = 0
    num_x = 0
    bingos_o = 0
    bingos_x = 0
    
    # get total number of each player's symbol
    for row in board :
        if 'O' in row :
            num_o += row.count('O')
        if 'X' in row :
            num_x += row.count('X')

    # get number of bingos
    for i in range(3) : 
        #horizontal
        if board[i][0] == board[i][1] == board[i][2] :
            if board[i][0] == 'O' :
                bingos_o += 1
            elif board[i][0] == 'X' :
                bingos_x += 1
        #vertical
        if board[0][i] == board[1][i] == board[2][i] :
            if board[0][i] == 'O' :
                bingos_o += 1
            if board[0][i] == 'X' :
                bingos_x += 1
    # diagonal
    if board[1][1] == 'O' :
        if board[0][0] == board[1][1] == board[2][2] :
            bingos_o += 1
        if board[0][2] == board[1][1] == board[2][0] :
            bingos_o += 1
    elif board[1][1] == 'X' :
        if board[0][0] == board[1][1] == board[2][2] :
            bingos_x += 1
        if board[0][2] == board[1][1] == board[2][0] :
            bingos_x += 1
    
    # fault check
    if not (1 >= num_o - num_x >= 0) :
        answer = error
    elif bingos_o != 0 and num_o != num_x + 1 :
        answer = error
    elif bingos_x != 0 and num_o != num_x :
        answer = error
    elif bingos_o > 0 and bingos_x > 0 :
        answer = error
    elif bingos_o == 2 and num_o != 5 :
        answer = error
    else : # normal game
        answer = normal
        
    return answer
반응형