문제/백준

[백준] 7682 틱택토 - Java

icodesiuuuu 2024. 10. 25. 17:30

문제

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

 


 

문제 개요

틱택토는 두 명이 번갈아 가며 말을 놓는 게임으로, 3×3 격자판에서 X와 O를 배치하여 가로, 세로, 또는 대각선 방향으로 연속된 3칸을 채우면 승리하는 게임입니다. 이 문제에서는 특정 틱택토 게임판 상태가 게임의 규칙을 준수하는 유효한 최종 상태인지 판별해야 합니다.

 

접근 방법

  1. 게임판 상태 입력 및 변환:
    • 입력을 받아 3x3 형태의 게임판으로 변환합니다.
    • 입력의 각 문자(X, O, .)는 게임판의 상태를 나타냅니다.
  2. 유효성 검사:
    • X와 O의 개수 조건: X의 개수는 항상 O보다 크거나 같고, 최대 1개 더 많아야 합니다.
    • 승리 조건 검사: X 또는 O가 승리 조건을 만족했는지 확인합니다.
    • 여러 승리 조건 확인:
      • 만약 X와 O가 동시에 승리하는 경우는 불가능하므로 유효하지 않습니다.
      • X가 승리했을 경우 X의 개수는 O보다 정확히 하나 많아야 합니다.
      • O가 승리했을 경우 X와 O의 개수가 같아야 합니다.
  3. 빈 칸 검사:
    • 승리자가 없는 경우, 게임판에 빈칸이 남아있다면 게임이 끝나지 않은 상태이므로 유효하지 않습니다.

 

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

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        String s = br.readLine();
        while (!s.equals("end")) {
            String[][] board = new String[3][3];
            int idx = 0;
            for (int i = 0; i < 3; i++) {
                for (int j = 0; j < 3; j++) {
                    board[i][j] = String.valueOf(s.charAt(idx++));
                }
            }
            System.out.println(isValid(board) ? "valid" : "invalid");
            s = br.readLine();
        }
    }

    public static boolean isValid(String[][] board) {
        int[] arr = cntNum(board);
        int x_cnt = arr[0];
        int o_cnt = arr[1];

        boolean x_correct = checkWin(board, "X");
        boolean o_correct = checkWin(board, "O");

        if (x_cnt < o_cnt) return false; // O가 더 많을 수 없음
        if (x_cnt - o_cnt >= 2) return false; // X와 O의 차이는 최대 1

        if (x_correct && o_correct) return false; // 두 플레이어가 동시에 승리 불가
        if (x_correct && x_cnt - o_cnt != 1) return false; // X가 승리하면 X가 O보다 하나 더 많아야 함
        if (!x_correct && o_correct && (x_cnt > o_cnt)) return false; // O가 승리하면 X와 O의 개수는 같아야 함
        if (!x_correct && !o_correct && checkEmpty(board)) return false; // 승리자 없고 빈칸이 남아 있으면 불가

        return true;
    }

    public static boolean checkEmpty(String[][] board) {
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                if (board[i][j].equals(".")) return true;
            }
        }
        return false;
    }

    public static int[] cntNum(String[][] board) {
        int x = 0;
        int o = 0;

        for (int i = 0; i < board.length; i++) {
            for (int j = 0; j < board[0].length; j++) {
                if (board[i][j].equals("X")) {
                    x++;
                } else if (board[i][j].equals("O")) {
                    o++;
                }
            }
        }
        return new int[]{x, o};
    }

    public static boolean checkWin(String[][] board, String player) {
        for (int i = 0; i < 3; i++) {
            if (board[i][0].equals(player) && board[i][1].equals(player) && board[i][2].equals(player))
                return true;
        }
        for (int i = 0; i < 3; i++) {
            if (board[0][i].equals(player) && board[1][i].equals(player) && board[2][i].equals(player))
                return true;
        }
        if (board[0][0].equals(player) && board[1][1].equals(player) && board[2][2].equals(player))
            return true;
        if (board[0][2].equals(player) && board[1][1].equals(player) && board[2][0].equals(player))
            return true;
        return false;
    }
}

'문제 > 백준' 카테고리의 다른 글

[백준] 4920 테트리스 게임 - Java  (0) 2024.10.30
[백준] 1654 랜선 자르기 - Java  (2) 2024.10.25
[백준] 3190 뱀 - Java  (1) 2024.10.24
[백준] 1094 막대기 - Java  (0) 2024.10.23
[백준] 1018 체스판 다시 칠하기 - Java  (0) 2024.10.23