All :L

[SWEA/Java] 추억의 2048 게임(6190) 본문

CODING/SWEA

[SWEA/Java] 추억의 2048 게임(6190)

ofijwe 2024. 8. 22. 14:16
반응형

https://swexpertacademy.com/main/code/problem/problemDetail.do?contestProbId=AWbrg9uabZsDFAWQ

 

SW Expert Academy

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

swexpertacademy.com

1. 문제 분석

문제 개요:
2048 게임에서 보드의 숫자들을 이동시키고 합치는 문제입니다. 주어진 방향(왼쪽, 오른쪽, 위, 아래)으로 모든 숫자들을 이동시키고 합쳐야 합니다. 각 숫자는 같은 숫자와 합쳐지며, 합쳐진 숫자는 이동 후 새로운 숫자가 됩니다.

입력 형식:

  1. 첫 줄에 테스트 케이스의 수 T가 주어진다.
  2. 각 테스트 케이스는 다음과 같은 형식이다.
    • 첫 줄에 보드의 크기 N과 이동 방향이 주어진다.
    • 다음 N줄에 보드의 상태가 주어진다. 각 줄은 N개의 정수로 구성된다.

출력 형식:

  • 각 테스트 케이스에 대해, 이동 후의 보드를 출력한다.

2. 알고리즘 종류

해당 문제는 "구현 및 시뮬레이션" 문제입니다. 각 방향에 대해 다음과 같은 작업을 수행합니다:

  • 왼쪽: 숫자를 왼쪽으로 이동시키고 합칩니다.
  • 오른쪽: 숫자를 오른쪽으로 이동시키고 합칩니다.
  • 위쪽: 숫자를 위쪽으로 이동시키고 합칩니다.
  • 아래쪽: 숫자를 아래쪽으로 이동시키고 합칩니다.

이 문제는 큐(Queue)  스택(Stack) 을 사용하여 구현됩니다. 각 방향에 따라 숫자들을 큐 또는 스택에 저장하고, 이를 통해 숫자들을 이동시키고 합치는 작업을 수행합니다.

3. 주요 부분 및 코드 작성 방법

1. 방향 처리:

  • 각 방향(왼쪽, 오른쪽, 위, 아래)에 대해 별도의 메서드를 작성하여 처리합니다.

2. 큐와 스택의 사용:

  • 왼쪽  위쪽: Queue를 사용하여 숫자를 왼쪽 또는 위쪽으로 이동시키며, 숫자가 같은 경우 합칩니다.
  • 오른쪽  아래쪽: Stack을 사용하여 숫자를 오른쪽 또는 아래쪽으로 이동시키며, 숫자가 같은 경우 합칩니다.

3. left() 메서드:

  • 각 줄의 숫자를 큐에 추가하여 왼쪽으로 이동시키고 합칩니다.
  • 큐를 이용해 숫자를 왼쪽으로 정렬하고 합칩니다.
  • 최종 결과를 answer 배열에 저장합니다.

4. right() 메서드:

  • 각 줄의 숫자를 스택에 추가하여 오른쪽으로 이동시키고 합칩니다.
  • 스택을 사용해 숫자를 오른쪽으로 정렬하고 합칩니다.
  • 최종 결과를 answer 배열에 저장합니다.

5. up() 메서드:

  • 각 열의 숫자를 큐에 추가하여 위쪽으로 이동시키고 합칩니다.
  • 큐를 이용해 숫자를 위쪽으로 정렬하고 합칩니다.
  • 최종 결과를 answer 배열에 저장합니다.

6. down() 메서드:

  • 각 열의 숫자를 스택에 추가하여 아래쪽으로 이동시키고 합칩니다.
  • 스택을 사용해 숫자를 아래쪽으로 정렬하고 합칩니다.
  • 최종 결과를 answer 배열에 저장합니다.

4. 코드 설명

왼쪽 이동 (left()):

public static void left() {
    Queue<Integer> q = new LinkedList<>();
    Queue<Integer> newQ = new LinkedList<>();
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            if (Board[i][j] != 0) q.add(Board[i][j]);
        }
        while (!q.isEmpty()) {
            if (q.size() == 1) {
                newQ.add(q.poll());
                break;
            }
            int n = q.poll();
            if (n == q.peek()) {
                int sum = n + q.poll();
                newQ.add(sum);
            } else {
                newQ.add(n);
            }
        }
        int k = 0;
        while (!newQ.isEmpty()) {
            answer[i][k++] = newQ.poll();
        }
    }
}
  • Queue를 사용하여 숫자들을 왼쪽으로 이동시키고, 같은 숫자는 합칩니다.
  • 처리된 결과를 answer 배열에 저장합니다.

오른쪽 이동 (right()):

public static void right() {
    Stack<Integer> s = new Stack<>();
    Stack<Integer> newS = new Stack<>();
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            if (Board[i][j] != 0) s.add(Board[i][j]);
        }
        while (!s.isEmpty()) {
            if (s.size() == 1) {
                newS.add(s.pop());
                break;
            }
            int n = s.pop();
            if (n == s.peek()) {
                int sum = n + s.pop();
                newS.add(sum);
            } else {
                newS.add(n);
            }
        }
        int k = 0;
        while (!newS.isEmpty()) {
            answer[i][N - newS.size()] = newS.pop();
        }
    }
}
  • Stack을 사용하여 숫자들을 오른쪽으로 이동시키고, 같은 숫자는 합칩니다.
  • 처리된 결과를 answer 배열에 저장합니다.

위쪽 이동 (up()):

public static void up() {
    Queue<Integer> q = new LinkedList<>();
    Queue<Integer> newQ = new LinkedList<>();
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            if (Board[j][i] != 0) q.add(Board[j][i]);
        }
        while (!q.isEmpty()) {
            if (q.size() == 1) {
                newQ.add(q.poll());
                break;
            }
            int n = q.poll();
            if (n == q.peek()) {
                int sum = n + q.poll();
                newQ.add(sum);
            } else {
                newQ.add(n);
            }
        }
        int k = 0;
        while (!newQ.isEmpty()) {
            answer[k++][i] = newQ.poll();
        }
    }
}
  • Queue를 사용하여 숫자들을 위쪽으로 이동시키고, 같은 숫자는 합칩니다.
  • 처리된 결과를 answer 배열에 저장합니다.

아래쪽 이동 (down()):

public static void down() {
    Stack<Integer> s = new Stack<>();
    Stack<Integer> newS = new Stack<>();
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            if (Board[j][i] != 0) s.add(Board[j][i]);
        }
        while (!s.isEmpty()) {
            if (s.size() == 1) {
                newS.add(s.pop());
                break;
            }
            int n = s.pop();
            if (n == s.peek()) {
                int sum = n + s.pop();
                newS.add(sum);
            } else {
                newS.add(n);
            }
        }
        int k = 0;
        while (!newS.isEmpty()) {
            answer[N - newS.size()][i] = newS.pop();
        }
    }
}
  • Stack을 사용하여 숫자들을 아래쪽으로 이동시키고, 같은 숫자는 합칩니다.
  • 처리된 결과를 answer 배열에 저장합니다.

5. 전체 코드

package SWEA6109_240821;

import java.io.*;
import java.util.*;

public class Solution {
	static int N;
	static int[][] Board, answer;
	
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		int T = Integer.parseInt(br.readLine());
		
		for(int tc = 1; tc <= T; tc++) {
			StringTokenizer st = new StringTokenizer(br.readLine());
			N = Integer.parseInt(st.nextToken());
			String direction = st.nextToken();
			Board = new int[N][N];
			answer = new int[N][N];
			
			for(int i = 0; i < N; i++) {
				st = new StringTokenizer(br.readLine(), " ");
				for(int j = 0; j < N; j++) Board[i][j] = Integer.parseInt(st.nextToken());
			}
			
			if(direction.equals("left")) left();
			else if(direction.equals("right")) right();
			else if(direction.equals("up")) up();
			else if(direction.equals("down")) down();

			System.out.println("#" + tc);
			for(int i = 0; i < N; i++) {
				for(int j = 0; j < N; j++) System.out.print(answer[i][j] + " ");
				System.out.println();
			}
		}
	}
	
	public static void left() {
		Queue<Integer> q = new LinkedList<>();
		Queue<Integer> newQ = new LinkedList<>();
		for(int i = 0; i < N; i++) { // 줄 별 계산
			int cnt = 0;
			for(int j = 0; j < N; j++) { // 각 줄의 숫자 q에 추가
				if(Board[i][j] != 0) q.add(Board[i][j]);
//				System.out.println(q);
			}
			while(!q.isEmpty()) { // q가 빌 때까지 반복
				if(q.size() == 1) {
					newQ.add(q.poll());
					break;
				}
				int n = q.poll();
				if(n == q.peek()) { // 같은 숫자를 만나면 
					int sum = n + q.poll();
					newQ.add(sum); // 합치기
				}
				else {
					newQ.add(n);
				}
			}
//			System.out.println("test : " + newQ);
			int k = 0;
			while(!newQ.isEmpty()) {
				answer[i][k++] = newQ.poll();
			}
		}
	}
	public static void right() {
		Stack<Integer> s = new Stack<>();
		Stack<Integer> newS = new Stack<>();
		for(int i = 0; i < N; i++) { // 줄 별 계산
			int cnt = 0;
			for(int j = 0; j < N; j++) { // 각 줄의 숫자 q에 추가
				if(Board[i][j] != 0) s.add(Board[i][j]);
//				System.out.println(s);
			}
			while(!s.isEmpty()) { // s가 빌 때까지 반복
				if(s.size() == 1) {
					newS.add(s.pop());
					break;
				}
				int n = s.pop();
				if(n == s.peek()) { // 같은 숫자를 만나면 
					int sum = n + s.pop();
					newS.add(sum); // 합치기
				}
				else {
					newS.add(n);
				}
			}
//			System.out.println("test : " + newS);
			int k = 0;
			while(!newS.isEmpty()) {
				answer[i][N - newS.size()] = newS.pop();
			}
		}
	}
	public static void up() {
		Queue<Integer> q = new LinkedList<>();
		Queue<Integer> newQ = new LinkedList<>();
		for(int i = 0; i < N; i++) { // 줄 별 계산
			int cnt = 0;
			for(int j = 0; j < N; j++) { // 각 줄의 숫자 q에 추가
				if(Board[j][i] != 0) q.add(Board[j][i]);
//				System.out.println(q);
			}
			while(!q.isEmpty()) { // q가 빌 때까지 반복
				if(q.size() == 1) {
					newQ.add(q.poll());
					break;
				}
				int n = q.poll();
				if(n == q.peek()) { // 같은 숫자를 만나면 
					int sum = n + q.poll();
					newQ.add(sum); // 합치기
				}
				else {
					newQ.add(n);
				}
			}
//			System.out.println("test : " + newQ);
			int k = 0;
			while(!newQ.isEmpty()) {
				answer[k++][i] = newQ.poll();
			}
		}
	}
	public static void down() {
		Stack<Integer> s = new Stack<>();
		Stack<Integer> newS = new Stack<>();
		for(int i = 0; i < N; i++) { // 줄 별 계산
			int cnt = 0;
			for(int j = 0; j < N; j++) { // 각 줄의 숫자 q에 추가
				if(Board[j][i] != 0) s.add(Board[j][i]);
//				System.out.println(s);
			}
			while(!s.isEmpty()) { // s가 빌 때까지 반복
				if(s.size() == 1) {
					newS.add(s.pop());
					break;
				}
				int n = s.pop();
				if(n == s.peek()) { // 같은 숫자를 만나면 
					int sum = n + s.pop();
					newS.add(sum); // 합치기
				}
				else {
					newS.add(n);
				}
			}
//			System.out.println("test : " + newS);
			int k = 0;
			while(!newS.isEmpty()) {
				answer[N - newS.size()][i] = newS.pop();
			}
		}
	}
}
반응형

'CODING > SWEA' 카테고리의 다른 글

[SWEA/Java] 나무 높이 (14510)  (0) 2024.09.12
[SWEA/Java] 디저트 카페 (2105)  (0) 2024.09.11
[SWEA/Java] 프로세서 연결하기 (1767)  (0) 2024.08.25
[SWEA/Java] 정사각형 방(1861)  (0) 2024.08.22
Comments