[SW Expert] 4615. 재미있는 오셀로 게임 (Java)
Algorithm/SW Expert Academy

[SW Expert] 4615. 재미있는 오셀로 게임 (Java)

728x90

문제 링크 : [SW Expert] 4615. 재미있는 오셀로 게임

 

SW Expert Academy

SW 프로그래밍 역량 강화에 도움이 되는 다양한 학습 컨텐츠를 확인하세요!

swexpertacademy.com

 

아이디어

1. N 값에 맞춰 보드판을 생성한다.

2. 입력받은 x, y 좌표에 바둑알 놓는다.

3. 놓은 위치에서 상, 하, 좌, 우, 대각선 총 8개 위치를 탐색, 내 바둑알이 있는지 확인한다.

4. 내 바둑알이 있다면 어디까지 바둑알을 뒤집을지 위치 확인한다.

5. 확인한 위치까지 바둑알을 뒤집는다.

 

후기

어린 시절에 많이 했었던 오셀로 게임을 구현하는 문제였다. 문제를 읽자마자 어떻게 구현해야 할지 감은 바로 왔지만, 구현하는 데 있어서는 꽤나 까다로웠다.

총 8방향의 모든 부분을 체크해줘야 하기 때문에 아래 그림과 같이 for문으로 0부터 7까지 탐색을 하며 방향을 나눠주었다.

방향에 맞춰 각각의 바둑알을 어떤 식으로 찾고, 뒤집을지는 switch문으로 나눠서 경우를 나눠서 구현을 했다. 모든 경우를 나눠서 구현을 했기 때문에 코드가 조금 길어졌다. 

 

처음으로 주어진 테스트 케이스를 통과하고 제출했을 때, 30개 중 19개를 통과했었다. 이유를 찾으러 디버깅을 하던 과정에서 찾은 문제점인데 공유하고자 한다.

아래 사진과 같이 (1,6) 위치에 돌을 놓는 경우, 정상적이라면 (2,5)의 돌만 뒤집어져야 한다. 하지만 가장 왼쪽에 있는 돌들이 전부 뒤집어지는 오류가 생겼다. 이유는 (1,4)에 있는 0을 처리를 안 해줬기 때문이다. 기존 코드에서는 while문으로 같은 바둑알이 나올 때까지 탐색하여 위치를 확인했지만, 이럴 경우엔 중간에 바둑알이 없는 경우 오류가 생긴다.

또한 입력받을 때의 좌표 값이 배열의 좌표 값과 다르다. 따라서 입력받을 때 y부터 받았고, x와 y 둘 다 1씩 감소시켜서 배열에 맞게끔 했다.

 

코드

import java.util.Scanner;

public class Main {
    public static short[][] board;
    public static int N;
    public static int[][] result;

    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);

        int T = scan.nextInt();
        result = new int[T][2];

        for (int i = 0; i < T; i++) {
            N = scan.nextInt();
            int M = scan.nextInt();

            board = initBoard(); // 보드판 초기화

            for (int j = 0; j < M; j++) {
                short y = scan.nextShort(); // 입력이 배열과 반대로 되어 있어서 x와 y 바꿔서 입력 받음
                short x = scan.nextShort();
                short turn = scan.nextShort(); // 1 or 2

                x--; // x, y 둘 다 1씩 줄여줌
                y--;

                board[x][y] = turn; // 바둑알 놓기

                changeStone(x, y, turn); // 바둑알
            }
            count(i); // 바둑알 갯수 카운팅
        }

        for (int i = 0; i < T; i++) { // 출력
            System.out.println("#" + (i + 1) + " " + result[i][0] + " " + result[i][1]);
        }
    }

    public static short[][] initBoard() { // 바둑판 초기화
        short[][] newBoard = new short[N][N];

        newBoard[N / 2 - 1][N / 2 - 1] = 2;
        newBoard[N / 2 - 1][N / 2] = 1;
        newBoard[N / 2][N / 2 - 1] = 1;
        newBoard[N / 2][N / 2] = 2;

        return newBoard;
    }

    public static void changeStone(int x, int y, short turn) {
        int[] dx = {-1, -1, -1, 0, 0, 1, 1, 1};
        int[] dy = {-1, 0, 1, -1, 1, -1, 0, 1};
        for (int i = 0; i < 8; i++) {
            int sideX = x + dx[i];
            int sideY = y + dy[i];

            if (sideX >= 0 && sideY >= 0 && sideX < N && sideY < N) { // 바둑판 밖으로 넘어갔을 경우 예외 처리
                if (board[sideX][sideY] == (3 - turn)) { // 3-turn : 1->2, 2->1
                    int[] target = findTarget(x, y, sideX, sideY, i); // 어디까지 돌을 바꿔야 하는지 위치 찾음

                    if (target != null) toggleStone(x, y, target[0], target[1], i); // 바둑알 뒤집음
                }
            }

        }
    }

    public static int[] findTarget(int x, int y, int sideX, int sideY, int i) {
        switch (i) {
            case 0:
                while (board[sideX--][sideY--] != board[x][y]) {
                    if (sideX < 0 || sideY < 0 || board[sideX][sideY] == 0) return null;
                }
                return new int[]{sideX + 1, sideY + 1};
            case 1:
                while (board[sideX--][sideY] != board[x][y]) {
                    if (sideX < 0 || board[sideX][sideY] == 0) return null;
                }
                return new int[]{sideX + 1, sideY};
            case 2:
                while (board[sideX--][sideY++] != board[x][y]) {
                    if (sideX < 0 || sideY >= N || board[sideX][sideY] == 0) return null;
                }
                return new int[]{sideX + 1, sideY - 1};
            case 3:
                while (board[sideX][sideY--] != board[x][y]) {
                    if (sideY < 0 || board[sideX][sideY] == 0) return null;
                }
                return new int[]{sideX, sideY + 1};
            case 4:
                while (board[sideX][sideY++] != board[x][y]) {
                    if (sideY >= N || board[sideX][sideY] == 0) return null;
                }
                return new int[]{sideX, sideY - 1};
            case 5:
                while (board[sideX++][sideY--] != board[x][y]) {
                    if (sideX >= N || sideY < 0 || board[sideX][sideY] == 0) return null;
                }
                return new int[]{sideX - 1, sideY + 1};
            case 6:
                while (board[sideX++][sideY] != board[x][y]) {
                    if (sideX >= N || board[sideX][sideY] == 0) return null;
                }
                return new int[]{sideX - 1, sideY};
            case 7:
                while (board[sideX++][sideY++] != board[x][y]) {
                    if (sideX >= N || sideY >= N || board[sideX][sideY] == 0) return null;
                }
                return new int[]{sideX - 1, sideY - 1};
        }
        return null;
    }

    public static void toggleStone(int x, int y, int tx, int ty, int i) {
        short turn = board[x][y];
        
        switch (i) {
            case 0:
                while (x-- != tx && y-- != ty) {
                    board[x][y] = turn;
                }
                break;
            case 1:
                while (x-- != tx) {
                    board[x][y] = turn;
                }
                break;
            case 2:
                while (x-- != tx && y++ != ty) {
                    board[x][y] = turn;
                }
                break;
            case 3:
                while (y-- != ty) {
                    board[x][y] = turn;
                }
                break;
            case 4:
                while (y++ != ty) {
                    board[x][y] = turn;
                }
                break;
            case 5:
                while (x++ != tx && y-- != ty) {
                    board[x][y] = turn;
                }
                break;
            case 6:
                while (x++ != tx) {
                    board[x][y] = turn;
                }
                break;
            case 7:
                while (x++ != tx && y++ != ty) {
                    board[x][y] = turn;
                }
                break;
        }
    }

    public static void count(int index) {
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                if (board[i][j] == 1) result[index][0]++;
                if (board[i][j] == 2) result[index][1]++;
            }
        }
        return;
    }
}

 



728x90