[프로그래머스]혼자서 하는 틱택토 with Java

hyeok ryu·2024년 5월 31일
1

문제풀이

목록 보기
146/154

문제

https://school.programmers.co.kr/learn/courses/30/lessons/160585


입력

  • 틱택토 게임판의 정보를 담고 있는 문자열 배열 board

출력

  • 나올 수 있는 게임 상황이면 1을 아니라면 0

풀이

제한조건

  • board의 길이 = board[i]의 길이 = 3
  • board의 원소는 모두 "O", "X", "."으로만 이루어져 있습니다.
  • board[i][j]는 i + 1행 j + 1열에 해당하는 칸의 상태를 나타냅니다.
    - "."은 빈칸을, "O"와 "X"는 해당 문자로 칸이 표시되어 있다는 의미입니다.

접근방법

단순 구현

단순 구현문제이다.
특별한 알고리즘을 요구하지는 않지만, 조건을 잘 이해하고 빼먹지 말아야 한다.

종료 조건을 바탕으로 어떤 케이스가 실수를 한 것인지 살펴보자.

  1. "O"를 표시할 차례인데 "X"를 표시하거나 반대로 "X"를 표시할 차례인데 "O"를 표시한다.
  2. 선공이나 후공이 승리해서 게임이 종료되었음에도 그 게임을 진행한다.

조건1을 살펴보자.
한 번씩 순서를 번갈아가며 표시를 한다.
따라서 O의 갯수와 X의 갯수는 같거나 O가 1개 더 많아야 한다

조건2의 경우를 살펴보자.
만약 O가 승리하는 경우라면,
O가 반드시 1개 더 표시한 상태에서 종료된다. ( O가 먼저 그리기 시작하므로 )

반대로 X가 승리하는 경우라면, O와 X의 표시한 갯수는 같아야 한다.

그리고 마지막으로 둘 다 승리하는 경우는 없다.
( 한명이 승리하면 바로 종료되어야 하기때문 )

즉 불가능한 경우를 정리하자면 아래와 같다.

1. 순서를 어긋나게 표시
2. 종료되었음에도 계속 진행된 경우
	a. 둘 다 승리하는 경우
    b. "O가 승리한다면, 반드시 하나 더 표시" 를 미 충족
    c. "X가 승리한다면, 반드시 동일 수 만큼 표시" 를 미 충족

코드

import java.util.Arrays;

class Solution {
	int SIZE = 3;
	char[][] arr = new char[SIZE][SIZE];

	public int solution(String[] board) {
		for (int i = 0; i < SIZE; ++i)
			arr[i] = board[i].toCharArray();

		// Step1. 순서가 어긋난 경우.
		int numP1 = getCount('O');
		int numP2 = getCount('X');
		if (!((numP1 == numP2) || (numP1 == numP2 + 1)))
			return 0;

		// Step2. 종료되었음에도 계속 진행된 경우
		boolean p1CanWin = canWin('O');
		boolean p2CanWin = canWin('X');

		// Step2-1. 둘 다 승리할 수 있게 두는 경우는 나오지 않는다.
		if (p1CanWin && p2CanWin)
			return 0;

		// Step2-2. p1가 승리한다면 반드시 하나 더 표시했다.
		if (p1CanWin && !(numP1 == numP2 + 1))
			return 0;

		// Step2-3. p2가 승리한다면 반드시 같은 수를 표시했다.
		if (p2CanWin && !(numP1 == numP2))
			return 0;

		return 1;
	}

	private boolean canWin(char c) {
		for (int i = 0; i < SIZE; ++i) {
			// 가로 체크
			if ((arr[i][0] == arr[i][1]) && (arr[i][0] == arr[i][2]) && (arr[i][0] == c))
				return true;
			// 세로 체크
			if ((arr[0][i] == arr[1][i]) && (arr[0][i] == arr[2][i]) && (arr[0][i] == c))
				return true;
		}
		// 좌상-우하 대각
		if ((arr[0][0] == arr[1][1]) && (arr[0][0] == arr[2][2]) && (arr[0][0] == c))
			return true;
		// 좌하-우상 대각
		if ((arr[0][2] == arr[1][1]) && (arr[0][2] == arr[2][0]) && (arr[0][2] == c))
			return true;

		return false;
	}

	public int getCount(char target) {
		return (int)Arrays.stream(arr)
			.flatMapToInt(chars -> new String(chars).chars())
			.filter(c -> c == target)
			.count();
	}
}

0개의 댓글