[백준] 7682. 틱택토 - python

     

     

    7682번: 틱택토

    입력은 여러 개의 테스트 케이스로 이루어져 있다. 각 줄은 9개의 문자를 포함하며, 'X', 'O', '.' 중 하나이다. '.'은 빈칸을 의미하며, 9개의 문자는 게임판에서 제일 윗 줄 왼쪽부터의 순서이다. 입

    www.acmicpc.net

    >> 요구사항

    틱택토 게임의 최종 상태가 될 수 있는지 판별하는 프로그램
    - x가 시작하고, 그 다음으로 o가 놓는다.
    - xxx 혹은 ooo가 발생하면 게임은 끝난다.
    - 혹은 어느 줄도 빙고가 나오지 않은 상태로 게임판이 다 차도 게임은 끝난다.

    >> 아이디어

    아래의 세 케이스 중 하나에 속하면 valid(최종상태로서 성립 가능), 그렇지 못하면 invalid(불가능)한 것으로 판단.
    1. x와 o 의 개수가 같으면서 / o 빙고줄은 존재하고, x 빙고줄은 존재하지 않는 게임판
    2. x 개수가 o 개수보다 하나 많으면서 / x 빙고줄은 존재하고, o 빙고줄은 존재하지 않는 게임판
    3. x 개수 5개 o 개수가 4개 이면서 / 어떠한 빙고줄도 존재하지 않는 게임판

     

    >>소스코드(메모리31256KB/실행시간48ms/결과PASS)

     

    def is_valid():
        x_num = 0  # x 개수
        o_num = 0  # o 개수
        x_bingo = 0  # x빙고줄('xxx') 개수
        o_bingo = 0  # o빙고줄('ooo') 개수
    
        # 개수 세기
        for i in range(3):
            for j in range(3):
                if game_board[i][j] == 'X':
                    x_num += 1
                if game_board[i][j] == 'O':
                    o_num += 1
    
        # 가로 순회하면서 빙고 세기
        for i in range(3):
            if game_board[i] == 'XXX':
                x_bingo += 1
            if game_board[i] == 'OOO':
                o_bingo += 1
    
        # 세로 순회하면서 빙고 세기
        for i in range(3):
            if transposed_board[i] == 'XXX':
                x_bingo += 1
            if transposed_board[i] == 'OOO':
                o_bingo += 1
    
        # 오른 대각선, 왼 대각선 체크해서 빙고 세기
        temp_right = ''
        temp_left = ''
        for i,j in [(0,0),(1,1),(2,2)]:
            temp_right += game_board[i][j]
            temp_left += game_board[i][2-j]
        if temp_right == 'XXX':
            x_bingo +=1
        if temp_right == 'OOO':
            o_bingo +=1
        if temp_left == 'XXX':
            x_bingo +=1
        if temp_left == 'OOO':
            o_bingo +=1
    
        if x_num == o_num and o_bingo and not x_bingo:
            return "valid"
        if x_num == o_num + 1 and x_bingo and not o_bingo:
            return "valid"
        if x_num == 5 and o_num == 4 and not x_bingo and not o_bingo:
            return "valid"
        return "invalid"
    
    while True:
        board = input()
        if board == 'end':
            break
    
        game_board = []
        for i in range(0,9,3):
            game_board.append(board[i:i+3])  # 세개 씩 끊어, 3*3게임판 만들기
    
        transposed_board = []
        for i in list(zip(*game_board)):
            transposed_board.append(''.join(i))  # 전치 행렬(세로 순회 때 편하려고 만듦)
    
        print(is_valid())
    반례가 너무 많아서 반대로 valid한 케이스 3가지를 도출해서 해결했다.
    but 도출할 때까지 들인 시간이 너무 길었음.....
    + 대문자, 소문자 주의 깊게 보기
    + 테스트 케이스 대충 이해하지 않기. 손으로 풀어보고 완전히 이해하고 로직 짜기.

    댓글