새소식

알고리즘 문제풀이/SWEA

[SWEA] 6109번 추억의 2048게임 자바(java) 풀이

  • -

sw expert academy 6109번 추억의 2048게임문제 자바(java) 풀이

문제정리

이는 2048 게임을 직접 해보는 것이 더 빠르게 이해할 수 있을 것 같다.
간단히 이야기 하자면 2의 배수로만 이루어진 타일들이 있는데
같은 숫자의 타일이 겹쳐지면 더해지는 게임이며 최종적으로 2048이라는 숫자를 가지는 타일을 만들면 끝나느 게임입니다.
2048게임 해보기


문제풀이

ArrayList를 중첩하여 이용하여 2차원 배열처럼 사용하여 게임판을 표현하였습니다.
전체적인 로직은 다음과 같습니다.

우선 ArrayList를 중첩하여 2차원 배열 처럼 사용할 수 있도록 초기화 합니다(initList)
그 다음 move 함수를 통해 움직입니다.
이때 방향에 따라 switch문을 통해 나누었습니다.
제가 생각하는 이 문제의 핵심은 오른쪽==위로, 왼쪽==아래 라는 것입니다.
오른쪽으로 이동하는 로직이랑 위로 이동시키는 로직이 같습니다.
위로 이동시킨다면 시계방향으로 맵을 회전 시켜서 오른쪽으로 이동시키는 것과 같습니다.

이를 이용하여 위나 아래로 이동하는 경우 list를 시계방향으로 뒤집고 로직을 수행한다음
다시 반시계 방향으로 뒤집어 원래대로 돌려주었습니다.


오른쪽으로 이동 로직

왼쪽과 오른쪽으로 이동의 로직은 같기 때문에 오른쪽으로 이동할때를 기준으로 설명드리겠습니다.
삽질을 많이 하다가 존재하는 0을 모두 제거하고 오른쪽에서 왼쪽으로 index를 이동하면서 확인한다면 된다는 것을 알게되었습니다. (정확히 기억 안나지만 3시간 정도는 한듯한...)

  1. 첫 행에 숫자가 0202와 같이 있다면 0을 제거합니다(22로 변함)
  2. 그 다음 오른쪽에서 왼쪽으로 이동하며 같은 숫자인지 확인합니다.
  3. 같은 숫자이면 값을 2배로 해주고 하나를 제거 합니다.
  4. 그리고 게임판의 크기 만큼 나머지를 0으로 채워줍니다. 오른쪽으로 이동이니 왼쪽에 0을 채웁니다(0004가 됨)

swea 6109 추억의 2048게임 자바 코드

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.IOException;
import java.util.ArrayList;

class Solution{    
    static ArrayList<ArrayList<Integer>> list;
    static int n;
    static String cmd;
    static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
    public static void main(String[] args) throws IOException{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int testNum = Integer.parseInt(br.readLine());

        for(int test=1; test<=testNum; test++){
            String[] temp = br.readLine().split(" ");
            n = Integer.parseInt(temp[0]);
            cmd = temp[1];

            list = initList();
            for(int i=0; i<n; i++){
                String[] temp2 = br.readLine().split(" ");
                for(int j=0; j<n; j++)
                    list.get(i).add(Integer.parseInt(temp2[j]));

            }

            move();
            bw.write("#" + test);
            bw.newLine();
            print();
        }
        bw.flush();
        bw.close();
        br.close();
    }

    public static void move(){
        switch(cmd){
            case "left":
                left(list);
                break;
            case "right":
                right(list);
                break;
            case "up":
                ArrayList<ArrayList<Integer>> reverse = rotateClockwise(list);
                right(reverse);
                list = rotateCounterClockwise(reverse);
                break;
            case "down":
                ArrayList<ArrayList<Integer>> reverse2 = rotateClockwise(list);
                left(reverse2);
                list = rotateCounterClockwise(reverse2);
        }
    }

    public static void left(ArrayList<ArrayList<Integer>> list){
        // 왼쪽에서 부터 확인
        for(int i=0; i<n; i++){
            for(int k=0; k<list.get(i).size()-1; k++)
                if(list.get(i).get(k) == 0){
                    list.get(i).remove(k);
                    k--;
                }
            int j = 0;
            while(j < list.get(i).size()-1){
                int left = list.get(i).get(j);
                int idx = j+1;

                int right = list.get(i).get(idx);

                // 값이 갖다면 합친다.
                if(left == right){
                    list.get(i).set(j, right*2);
                    list.get(i).remove(idx);
                    list.get(i).add(0);
                }

                j = idx;
            }

            // 길이가 n이 될때까지 0을 왼쪽에 채움
            while(list.get(i).size() != n)
                list.get(i).add(0);
        }
    }

    public static void right(ArrayList<ArrayList<Integer>> list){
        // 위에부터 확인
        // 오른쪽에서 부터 확인


        for(int i=0; i<n; i++){
            // 0을 다 없앰
            for(int k=0; k<=list.get(i).size()-1; k++)
                if(list.get(i).get(k) == 0){
                    list.get(i).remove(k);
                    k--;
                }

            int j = list.get(i).size() - 1;
            while(j > 0){
                int right = list.get(i).get(j);
                int idx = j-1;

                int left = list.get(i).get(idx);

                // 값이 갖다면 합친다.
                if(left == right){
                    list.get(i).set(j, right*2);
                    list.get(i).remove(idx);
                    list.get(i).add(0, 0);
                }


                j = idx;
            }

            // 길이가 n이 될때까지 0을 왼쪽에 채움
            while(list.get(i).size() != n)
                list.get(i).add(0,0);
        }
    }

    public static ArrayList<ArrayList<Integer>> rotateClockwise(ArrayList<ArrayList<Integer>> list){        
        ArrayList<ArrayList<Integer>> reverse = initList();
        for(int i=0; i<n; i++){
            for(int j=n-1; j>=0; j--){
                reverse.get(i).add(list.get(j).get(i));
            }
        }
        return reverse;
    }

    public static ArrayList<ArrayList<Integer>> rotateCounterClockwise(ArrayList<ArrayList<Integer>> list){        
        ArrayList<ArrayList<Integer>> reverse = initList();
        for(int i=0; i<n; i++){
            for(int j=0; j<n; j++){
                reverse.get(i).add(list.get(j).get(n-1-i));
            }
        }
        return reverse;
    }

    public static ArrayList<ArrayList<Integer>> initList(){
        ArrayList<ArrayList<Integer>> board = new ArrayList<>();
        for(int i=0; i<n; i++){
            board.add(new ArrayList<Integer>());
        }
        return board;
    }

    public static void print() throws IOException{
        for(int i=0; i<n; i++){
            for(int j=0; j<n; j++){
                bw.write(list.get(i).get(j) + "");
                // 마지막에 띄어쓰기 방지
                if(j != n-1)
                    bw.write(" ");
            }
            bw.newLine();
        }
    }
}
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.