알고리즘/백준

백준 7682 - 틱택토 (Java)

D_Helloper 2024. 4. 22. 21:13

https://www.acmicpc.net/problem/7682

 

7682번: 틱택토

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

www.acmicpc.net

문제

틱택토 게임은 두 명의 사람이 번갈아가며 말을 놓는 게임이다. 게임판은 3×3 격자판이며, 처음에는 비어 있다. 두 사람은 각각 X 또는 O 말을 번갈아가며 놓는데, 반드시 첫 번째 사람이 X를 놓고 두 번째 사람이 O를 놓는다. 어느 때든지 한 사람의 말이 가로, 세로, 대각선 방향으로 3칸을 잇는 데 성공하면 게임은 즉시 끝난다. 게임판이 가득 차도 게임은 끝난다.

게임판의 상태가 주어지면, 그 상태가 틱택토 게임에서 발생할 수 있는 최종 상태인지를 판별하시오.

입력

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

출력

각 테스트 케이스마다 한 줄에 정답을 출력한다. 가능할 경우 "valid", 불가능할 경우 "invalid"를 출력한다.

예제 입력 1 복사

XXXOO.XXX
XOXOXOXOX
OXOXOXOXO
XXOOOXXOX
XO.OX...X
.XXX.XOOO
X.OO..X..
OOXXXOOXO
end

예제 출력 1 복사

invalid
valid
invalid
valid
valid
invalid
invalid
invalid

 

풀이

먼저 게임이 끝나는 경우를 생각해본다.

1. X가 이긴 경우

1-1. 게임 판이 가득차고 O가 완성되지 않은 경우

1-2. O가 완성되지 않고 X가 완성 된 경우

2. O가 이긴 경우

2-1. X가 완성되지 않고 O가 완성된 경우

위와 같은 상황이 valid 상황이다. 게임이 정상적으로 끝난 상황들.

남은 상황들은 invalid 상황이다. 게임이 정상적으로 끝나지 않은 상황.

틱택토가 완성되었는지 검사는 3x3 사이즈이기 때문에

한 열씩, 한 행씩 같은 것으로 채워져 있는지 검사하고, 대각선은 좌상에서 우하로, 우상에서 좌하로 검사하면 모든 검사가 마쳐진다.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class BJ_7682_틱택토 {
    static char[][] map;
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        while(true)
        {
            String str = br.readLine();
            if(str.equals("end"))
                break;
            map = new char[3][3];
            int xCnt = 0;
            int oCnt = 0;
            int index = 0;

            for(int i=0; i<3; i++)
            {
                for(int j=0; j<3; j++)
                {
                    map[i][j] = str.charAt(index++);
                    if(map[i][j]=='X')
                        xCnt++;
                    else if(map[i][j] =='O')
                        oCnt++;
                }
            }

            // X가 이긴 경우
            if(xCnt == oCnt+1){
                // 판이 가득차고 O가 완성되지 않은 경우
                if(xCnt+oCnt == 9 && !bingo('O'))
                    System.out.println("valid");
                // O가 완성 되지 않고, X가 완성 된 경우
                else if(!bingo('O') && bingo('X'))
                    System.out.println("valid");
                // 둘 다 아닌 경우는 X도 이기지 못함
                else
                    System.out.println("invalid");
            }
            // O가 이긴 경우
            else if(xCnt == oCnt)
            {
                // X가 완성되지 않고, O가 완성된 경우
                if(!bingo('X') && bingo('O'))
                    System.out.println("valid");
                // 그게 아니라면 먼저 두는 것은 X이기 때문에 이길 수 없음
                else
                    System.out.println("invalid");
            }
            // 둘 다 완성되지 않은 경우
            else
                System.out.println("invalid");
        }
    }
    public static boolean bingo(char c)
    {
        for(int i=0; i<3; i++)
        {
            // 가로 한줄로 성공한 경우
            if(map[i][0] == c && map[i][1] == c && map[i][2] == c)
                return true;
        }
        for(int i=0; i<3; i++)
        {
            // 세로 한줄로 성공한 경우
            if(map[0][i] == c && map[1][i] == c && map[2][i] == c)
                return true;
        }
        // 대각선으로 성공한 경우, 좌상에서 우하로
        if(map[0][0] == c && map[1][1] == c && map[2][2] == c)
            return true;
        // 대각선으로 성공한 경우, 우상에서 좌하로
        if(map[0][2] == c && map[1][1] == c && map[2][0] == c)
            return true;
        // 여기까지 return이 없을 경우 끝나지 않음
        return false;
    }
}