코딩 테스트(Coding Test)/백준
[백준] 9090번 : 틱택토 이기기 - 자바(Java)
다문다뭉
2024. 11. 3. 17:42
Problem 🔒
문제
https://www.acmicpc.net/problem/9290
남규는 재우와 틱택토를 하던 도중, 거의 이기기 직전에 다다랐다! 남규의 승리로부터 단 한 단계 전의 틱택토 게임판이 주어졌을 때, 승리를 위해 말을 어디에 놓아야 할지 알아내자.
입력
첫 번째 줄에는 테스트 케이스의 개수가 주어진다.
각 테스트 케이스는 현재 틱택토 게임판의 상태를 3줄에 걸쳐 나타내며, 그 다음 줄에는 남규의 말(x 또는 o)이 무엇인지가 주어진다. 게임판의 상태는 'x', 'o', '-'(빈칸)으로 이루어진다. 반드시 다음 한 번의 행동으로 남규가 게임을 이길 수 있는 상태만 주어진다.
출력
각 테스트 케이스마다 "Case x:"와 공백을 출력한 후, 아래의 3줄에 걸쳐 남규가 다음 한 수로 이긴 후 게임판의 상태를 출력한다. x는 테스트 케이스의 번호이며, 1부터 시작한다.
더보기
예제 입력 1
3
o--
-o-
xx-
x
o-x
--o
x--
x
xx-
o-o
---
o
예제 출력 1
Case 1:
o--
-o-
xxx
Case 2:
o-x
-xo
x--
Case 3:
xx-
ooo
---
Approach ⭕
- 'O'와 'X' 위치 저장
- 게임판을 읽으면서 'O'와 'X' 위치를 저장했다.
- 남규의 말이 무엇인지는 게임판을 읽은 후, 알려주기 때문에 'O'와 'X' 위치 둘 다 저장했다.
- 남규의 말 위치 저장
- 남규가 사용하는 말의 해당 좌표를 Apoint 배열에 복사했다.
- 이길 수 있는 위치 찾기
- Apoint의 두 좌표에 따라 케이스를 나눠서 처리
- 행이 같은 경우, 해당 행에서 비어있는 위치에 말을 놓았다.
- 열이 같은 경우, 해당 열에서 비어있는 위치에 말을 놓았다.
- 대각선인 경우, 비어있는 대각선 위치에 말을 놓았다.
- 비어있는 위치 계산
- 게임판의 인덱스는 항상 0, 1, 2로 이루어져 있어 인덱스의 합은 항상 3이다.
- 현재 말이 있는 위치의 인덱스 합을 3에서 빼면, 나머지 빈 칸의 인덱스를 찾을 수 있다.
- Apoint의 두 좌표에 따라 케이스를 나눠서 처리
주의할 점
발생할 수 있는 2가지의 대각선을 서로 구분할 필요가 없다. 비어있는 위치 계산식이 항상 같다.
Solution 💡
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class 틱택토이기기 {
static String[][] map;
static String nam;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int tc = Integer.parseInt(st.nextToken()); // 테케
for(int t=0; t<tc; t++){
map = new String[3][3];
// O좌표 2개, X좌표 2개
int oS = 0;
int xS = 0;
int[][] Opoint = new int[2][2];
int[][] Xpoint = new int[2][2];
// 현재 게임판
for(int i=0; i<3; i++){
String rline = br.readLine();
String[] tokens = rline.split("");
for(int j=0; j<3; j++){
map[i][j] = tokens[j];
if(map[i][j].equals("o")){
Opoint[oS][0] = i;
Opoint[oS++][1] = j;
}
if(map[i][j].equals("x")){
Xpoint[xS][0] = i;
Xpoint[xS++][1] = j;
}
}
}
// 남규 말
nam = br.readLine();
int[][] Apoint = new int[2][2];
if (nam.equals("o")){
for(int i=0; i<2; i++){
for(int j=0; j<2; j++){
Apoint[i][j] = Opoint[i][j];
}
}
}else{
for(int i=0; i<2; i++){
for(int j=0; j<2; j++){
Apoint[i][j] = Xpoint[i][j];
}
}
}
// 케이스 나누기
if(Apoint[0][0] == Apoint[1][0]){
// 행이 같을 때
int tmp = 3 - (Apoint[0][1] + Apoint[1][1]);
map[Apoint[0][0]][tmp] = nam;
}else if(Apoint[0][1] == Apoint[1][1]){
// 열이 같을 때
int tmp = 3 - (Apoint[0][0] + Apoint[1][0]);
map[tmp][Apoint[0][1]] = nam;
}else {
// 대각선
int tmp1 = 3 - (Apoint[0][0] + Apoint[1][0]);
int tmp2 = 3 - (Apoint[0][1] + Apoint[1][1]);
map[tmp1][tmp2] = nam;
}
PrintGraph(map, t+1);
}// tc
}
public static void PrintGraph(String[][] graph, int t){
System.out.println("Case " + t + ":");
for (String[] row : graph) {
for (String e : row) {
System.out.print(e);
}
System.out.println();
}
}
}