Problem 🔒
문제
https://www.acmicpc.net/problem/7682
틱택토 게임은 두 명의 사람이 번갈아가며 말을 놓는 게임이다. 게임판은 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
Approach ⭕
- X말과 O말의 개수 확인
- 정상적인 게임 판이라면 0≤ (X-O) ≤1을 만족해야한다.
- 승리했는지 여부 확인
- X와 O중에서 누가 승리했는지 확인한다.(Win 메서드)
- 가능한 승리 조건을 able 배열에 저장한다.
- 각 조건을 확인하면서 3칸이 모두 같은 문자인 경우 승리했다고 판단한다.
- 승리한 경우, 가능한 게임 상황인지 판별한다.
- X와 O 둘 다 승리하는 경우는 불가능하다.
- X가 승리한 경우, X말의 수가 O말의 수보다 많아야 한다.
- O가 승리한 경우, X말의 수와 O말의 수가 같아야 한다.
- X와 O중에서 누가 승리했는지 확인한다.(Win 메서드)
- 이전 조건들을 통과했다면, 게임판이 꽉 찼는지 확인한다.
- 승부가 결정되지 않은 상태로, 게임판이 다 찼다면 valid로 처리한다.
- 위의 조건들에서 처리되지 않았다면, invalid로 처리한다.
Solution 💡
import java.util.Scanner;
public class 틱택토 {
static int[][] able = {{0,1,2},{3,4,5},{6,7,8},{0,3,6},{1,4,7},{2,5,8},{0,4,8},{2,4,6}};
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
Scanner sc = new Scanner(System.in);
boolean B = true;
while (B){
String game = sc.next();
if(game.equals("end")){B=false; break;} // 입력 끝
int nX=0, nO=0;// X말 개수, O말 개수
char[] map = new char[9];
for(int i=0; i<9; i++){
map[i] = game.charAt(i);
if(map[i]=='X') nX++;
if(map[i]=='O') nO++;
}
// 1. X말 개수와 O말 개수 차이 확인
if(nX-nO!=0 && nX-nO!=1) {sb.append("invalid").append("\\n"); continue;}
// 2. 승리한 사람이 있는지 확인
boolean Xwin = Win(map, 'X');
boolean Owin = Win(map, 'O');
if(Xwin && Owin) {sb.append("invalid").append("\\n"); continue;}
if(Xwin){ if(nX>nO){sb.append("valid").append("\\n"); continue;} else{sb.append("invalid").append("\\n"); continue;}}
if(Owin){ if(nX==nO){sb.append("valid").append("\\n"); continue;} else{sb.append("invalid").append("\\n"); continue;}}
// 3. 1,2단계를 다 통과하고, 모든 말이 다 찼으면 valid
if(nX+nO==9) {sb.append("valid").append("\\n"); continue;}
// 4. 그 외 나머지는 invalid
sb.append("invalid").append("\\n");
}// while
System.out.println(sb);
}
public static boolean Win(char[] map, char h){
for(int[] idx : able){
if(map[idx[0]]==h && map[idx[1]]==h && map[idx[2]]==h){
return true;
}
}
return false;
}
}
개선할 점 🔧
- 입력 종료 시 “end”가 주어졌을때, while문 안에서 break만 써도 while문이 종료된다.
- 승리했는지 여부 확인 후, 가능한 게임 상황인지 확인할 때 중복된 조건을 제거하고, else문을 활용한다면 더욱 구조화된 코드를 작성할 수 있다.
- X와 O가 동시에 승리하는 경우를 처리했는데 다음 조건에서 한 번 더 확인했다.
- if문을 남발하여 코드가 산만하고 구조적이지 않았다.
// 2. 승리한 사람이 있는지 확인 boolean Xwin = Win(map, 'X'); boolean Owin = Win(map, 'O'); if(Xwin && Owin) {sb.append("invalid").append("\\n"); continue;} if(Xwin && !Owin && nX>nO) {sb.append("valid").append("\\n"); continue;} if(Owin && !Xwin && nX==nO) {sb.append("valid").append("\\n"); continue;} if(Owin && !Xwin && nX>nO) {sb.append("invalid").append("\\n"); continue;}
결과
'코딩 테스트(Coding Test) > 백준' 카테고리의 다른 글
[백준] 17142번 : 연구소 3 - 자바(Java) (0) | 2024.11.08 |
---|---|
[백준] 17141번 : 연구소 2 - 자바(Java) (0) | 2024.11.08 |
[백준] 4179번 : 불! - 자바(Java) (0) | 2024.11.06 |
[백준] 20055번 : 컨베이어 벨트 위의 로봇 - 자바(Java) (2) | 2024.11.06 |
[백준] 5427번 : 불 - 자바(Java) (0) | 2024.11.05 |