[백준 JAVA] 12100 : 2048 (Easy)
2024. 7. 8. 22:22ㆍ백준
[백준 12100] 2048 (Easy) : https://www.acmicpc.net/problem/12100
문제 조건 정리
- 같은 값을 갖는 두 블록이 충돌하면 두 블록은 하나로 합쳐지게 된다.
- 한 번의 이동에서 이미 합쳐진 블록은 또 다른 블록과 다시 합쳐질 수 없다.
- 실제 게임에서는 이동을 한 번 할 때마다 블록이 추가되지만, 이 문제에서 블록이 추가되는 경우는 없다.
- 똑같은 수가 세 개가 있는 경우에는 이동하려고 하는 쪽의 칸이 먼저 합쳐진다.
입력 및 출력
- 첫째 줄에 보드의 크기 N (1 ≤ N ≤ 20)이 주어진다.
- 둘째 줄부터 N개의 줄에는 게임판의 초기 상태가 주어진다.
0은 빈 칸을 나타내며, 이외의 값은 모두 블록을 나타낸다. - 블록에 쓰여 있는 수는 2보다 크거나 같고, 1024보다 작거나 같은 2의 제곱꼴이다. 블록은 적어도 하나 주어진다.
- 최대 5번 이동시켜서 얻을 수 있는 가장 큰 블록을 출력한다.
문제를 풀면서
- 일단 2048 게임을 한판 했다.
- 블럭을 이동할 때, 새로운 블럭이 생기지 않아서 간단히 구현 가능하다고 생각했다.
- 이동과 합체 과정을 한번에 진행하려고 하니 올바르게 작동하지 않았다.
- 군데군데 0이 박힌 모습을 보고, 역시 프린트 찍어봐야한다고 생각했다.
- 결국 이동, 합체, 이동 3단계로 나뉜 단계를 차례로 진행했다.
- 왼쪽은 왼쪽에서부터 당겨야하고
오른쪽은 오른쪽에서 당겨야한다는 점을 간과해서 또 고쳤다.
코드
package baekJoon;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class BJ12100 {
static int n;
static int maxValue = 0;
public static void main(String[] args) throws IOException {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
n = Integer.parseInt(bufferedReader.readLine());
int[][] board = new int[n][n];
for (int i = 0; i < n; i++) {
StringTokenizer stringTokenizer = new StringTokenizer(bufferedReader.readLine(), " ");
for (int j = 0; j < n; j++) {
board[i][j] = Integer.parseInt(stringTokenizer.nextToken());
}
}
simulate(board, 5);
System.out.println(maxValue);
}
private static void simulate(int[][] board, int count) {
if (count == 0) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
maxValue = Math.max(maxValue, board[i][j]);
}
}
return;
}
for (int d = 0; d < 4; d++) {
int[][] newBoard = copyBoard(board);
newBoard = move(d, newBoard);
simulate(newBoard, count - 1);
}
}
private static int[][] move(int d, int[][] board) {
// System.out.println("d = " + d);
// System.out.println("d0 d1 d2 d3");
// System.out.println("좌 우 상 하");
// System.out.println();
board = shift(d, board);
// for (int i = 0; i < n; i++) {
// for (int j = 0; j < n; j++) {
// System.out.print(board[i][j] + " ");
// }
// System.out.println();
// }
// System.out.println();
board = merge(d, board);
// for (int i = 0; i < n; i++) {
// for (int j = 0; j < n; j++) {
// System.out.print(board[i][j] + " ");
// }
// System.out.println();
// }
// System.out.println();
board = shift(d, board);
// for (int i = 0; i < n; i++) {
// for (int j = 0; j < n; j++) {
// System.out.print(board[i][j] + " ");
// }
// System.out.println();
// }
// System.out.println();
// System.out.println();
// System.out.println();
return board;
}
private static int[][] shift(int d, int[][] board) {
if (d == 0) { // 좌로 밀착
for (int i = 0; i < n; i++) {
int[] temp = new int[n];
int idx = 0;
for (int j = 0; j < n; j++) {
if (board[i][j] == 0) continue;
temp[idx++] = board[i][j];
}
board[i] = temp;
}
}
if (d == 1) { // 우로 밀착
for (int i = 0; i < n; i++) {
int[] temp = new int[n];
int idx = n - 1;
for (int j = n - 1; j >= 0; j--) {
if (board[i][j] == 0) continue;
temp[idx--] = board[i][j];
}
board[i] = temp;
}
}
if (d == 2) { // 위로 밀착
for (int j = 0; j < n; j++) {
int[] temp = new int[n];
int idx = 0;
for (int i = 0; i < n; i++) {
if (board[i][j] == 0) continue;
temp[idx++] = board[i][j];
}
for (int i = 0; i < n; i++) {
board[i][j] = temp[i];
}
}
}
if (d == 3) { // 아래로 밀착
for (int j = 0; j < n; j++) {
int[] temp = new int[n];
int idx = n - 1;
for (int i = n - 1; i >= 0; i--) {
if (board[i][j] == 0) continue;
temp[idx--] = board[i][j];
}
for (int i = 0; i < n; i++) {
board[i][j] = temp[i];
}
}
}
return board;
}
private static int[][] merge(int d, int[][] board) {
if (d == 0) { // 좌
for (int i = 0; i < n; i++) {
for (int j = 0; j < n-1; j++) {
if (board[i][j] == 0) continue;
if (board[i][j] == board[i][j + 1]) {
board[i][j] *= 2;
board[i][j+1] = 0;
j++;
}
}
}
return board;
}
if (d == 1) { // 우
for (int i = 0; i < n; i++) {
for (int j = n-1; j >0; j--) {
if (board[i][j] == 0) continue;
if (board[i][j] == board[i][j - 1]) {
board[i][j] *= 2;
board[i][j-1] = 0;
j--;
}
}
}
return board;
}
if (d == 2) { // 상
for (int j = 0; j < n; j++) {
for (int i = 0; i < n - 1; i++) {
if (board[i][j] == 0) continue;
if (board[i][j] == board[i + 1][j]) {
board[i][j] *= 2;
board[i + 1][j] = 0;
i++;
}
}
}
return board;
}
if (d == 3) { // 하
for (int j = 0; j < n; j++) {
for (int i = n - 1; i > 0; i--) {
if (board[i][j] == 0) continue;
if (board[i][j] == board[i - 1][j]) {
board[i][j] *= 2;
board[i - 1][j] = 0;
i--;
}
}
}
return board;
}
return board;
}
private static int[][] copyBoard(int[][] board) {
int[][] newBoard = new int[n][n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
newBoard[i][j] = board[i][j];
}
}
return newBoard;
}
}
문제를 풀고 난 후
백트래킹이 기반이 되는 시뮬레이션 문제를 풀다보니 백트래킹은 문제가 아닌 것을 이제야 알겠다.
문제를 해결하기 위해서 어떻게 접근해야하는지 더욱 깊게 생각해야했다.
이런 문제들을 풀 때, 최대한 함수는 쪼개고 단순하게, 그리고 아직까지는 디버깅을 위해서 출력을 찍어보는 습관이 필요할 것 같다.
'백준' 카테고리의 다른 글
[백준 JAVA] 15684 : 사다리 조작 (0) | 2024.07.10 |
---|---|
[백준 JAVA] 17142 : 연구소 3 (0) | 2024.07.10 |
[백준 JAVA] 1644 : 소수의 연속합 (0) | 2024.07.07 |
[백준 JAVA] 1300 : K번째 수 (0) | 2024.07.05 |
[백준 JAVA] 2042 : 구간 합 구하기 (0) | 2024.07.03 |