[구름톤 챌린지] 2주차 학습 일기 (2)

밤새·2023년 8월 26일
0

구름톤 챌린지

목록 보기
4/4
post-thumbnail

구름문제 IDE 문제 9~10

9, 10일차 문제는 저번 문제에서 배운 것들을 활용하여 문제를 푸는 것이 많아서 한 번 문제들을 코드 분석을 해보도록 하겠다!


문제 9. 폭탄 구현하기 (2)

관련 문제를 풀고 싶다면?
폭탄 구현하기 (2) - 구름LEVEL

해당 문제는 폭탄 구현하기 문제에서 조건을 더 추가한 완전 탐색 문제이다. 요구 사항을 정확히 구현해야 한다. N사 기출문제를 반영한 문제이다.

1) 필요한 개념 ✨

  • 시뮬레이션
  • 행렬

2) 분석 ✍🏻

폭탄 구현하기(2) 문제는 기존의 폭탄 구현하기 문제에 몇 가지 조건이 추가된 문제이다. 문제를 분석하면 아래와 같이 정리할 수 있을 꺼 같다.

  • 폭탄이 떨어지면, 떨어진 위치를 기준으로 십자가 영역의 폭탄 값이 조건에 따라서 증가
    • #는 폭탄 값의 영향을 받지 않음.
    • 0 이라면 폭탄 값이 1만큼 증가
    • @ 라면 폭탄 값이 2만큼 증가
  • 모든 폭탄이 떨어진 이후에, 폭탄 값이 가장 높은 값을 출력

위의 상태에서 K 개의 폭탄이 모두 떨어지는 것을 시뮬레이션 하면 문제는 해결할 수 있다.

3) 문제 풀이 💡

문제 풀이를 위해서 필요한 점들을 고민하면 우선 2차원 배열에서의 탐색이 필요하다.

이후에는 시뮬레이션 문제이기 때문에 주어지는 폭탄 데이터를 입력 받아 문제의 요구 사항대로 구현하면 된다. 모든 폭탄이 떨어진 이후에, 행렬에서 가장 큰 값을 찾아야 한다.

4) 코드 💻

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // 사용자로부터 N과 K를 입력 받습니다.
        int N = scanner.nextInt(); // 행과 열의 크기
        int K = scanner.nextInt(); // 작업 횟수
        scanner.nextLine(); // 이전에 입력 받은 줄 바꿈 문자를 처리
        
        // N x N 크기의 문자열 배열을 생성하여 게임 판을 구성합니다.
        String[][] matrix = new String[N][N];
        for (int i = 0; i < N; i++) {
            matrix[i] = scanner.nextLine().split(" "); // 공백을 기준으로 문자열을 분리하여 배열에 저장
        }

        // 상하좌우로 이동하기 위한 변화량을 정의합니다.
        int[] dx = {0, 0, 0, 1, -1};
        int[] dy = {0, 1, -1, 0, 0};
        
        // 각 위치별 점수를 저장할 2차원 배열을 생성합니다.
        int[][] score = new int[N][N];

        // K번의 작업을 수행합니다.
        for (int k = 0; k < K; k++) {
            int x = scanner.nextInt() - 1; // 사용자 입력은 1부터 시작하므로 배열 인덱스에 맞게 조정
            int y = scanner.nextInt() - 1;
            
            // 상하좌우로 이동하여 점수를 계산합니다.
            for (int i = 0; i < 5; i++) {
                int nx = x + dx[i]; // 다음 위치 계산
                int ny = y + dy[i];
                
                // 범위 내에 있는지 확인하고, '#'이 아니라면 점수 부여
                if (0 <= nx && nx < N && 0 <= ny && ny < N) {
                    if (!matrix[nx][ny].equals("#")) { // '#'이 아니면
                        if (matrix[nx][ny].equals("@")) { // '@'이면 2점 추가
                            score[nx][ny] += 2;
                        } else { // 그 외의 경우 1점 추가
                            score[nx][ny] += 1;
                        }
                    }
                }
            }
        }

        // 최종 결과를 계산합니다.
        int result = 0;
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                result = Math.max(result, score[i][j]); // 최대 점수 갱신
            }
        }

        // 결과를 출력합니다.
        System.out.println(result);
        
        // Scanner 객체를 닫아 리소스를 해제합니다.
        scanner.close();
    }
}

5) 코드 분석 🤔

  1. 사용자로부터 입력 받기 :

    • Scanner 클래스를 사용하여 사용자로부터 정수 값을 입력 받는다.
    • 입력 받은 값은 N과 K로 저장된다. N은 행과 열의 크기를 나타내며, K는 게임에서 수행할 작업의 횟수를 나타낸다.
  2. 매트릭스 구성 :

    • N 크기의 2차원 문자열 배열 matrix를 생성한다. 이 배열은 게임 판을 나타내며, 각 위치는 문자열로 채워진다.
    • 사용자로부터 N개의 줄에 걸쳐 문자열을 입력 받아서 매트릭스에 저장한다.
  3. 이동과 점수 계산 :

    • dxdy 배열은 이동 방향을 나타내는 상대적인 변화량을 담고 있다.
    • K번의 작업을 수행하면서 해당 위치에서 상하좌우로 이동하여 인접한 위치에 점수를 부여한다.
    • 이동한 위치에 '#' 문자가 아닌 경우에만 점수를 부여하며, '@' 문자일 경우 2점을 추가하고 그 외의 경우에는 1점을 추가한다.
  4. 최종 결과 계산 :

    • 모든 작업을 수행한 후, 각 위치에서 얻은 점수를 계산한다.
    • 각 위치에서 얻은 점수 중 가장 큰 값을 찾아 result 변수에 저장한다.
  5. 결과 출력 :

    • 계산된 최대 점수인 result를 출력한다.
  6. Scanner 객체 닫기 :

    • 입력 처리가 끝난 후에는 Scanner 객체를 닫아 리소스 누수를 방지한다.


문제 10. GameJam

관련 문제를 풀고 싶다면?
GameJam - 구름LEVEL

해당 문제는 시뮬레이션 문제로, 다양한 조건과 요구 사항을 모두 만족하도록 구현해야 한다. 국비 교육 적성고사 변형 문제이다.

1) 필요한 개념 ✨

  • 시뮬레이션

2) 분석 ✍🏻

GameJam 문제는 폭탄 구현하기 (2)와 비슷한 문제이지만, 조금 더 어렵다. 규칙은 단순하지만, 규칙의 특성과 모든 조건을 따지면서, 구현하는 능력이 필요하다.

또한, 등장하는 2개의 캐릭터의 이동하는 논리는 동일하다. 즉 각각 캐릭터에 대해서 구현하기 보다는 함수를 통해서 간결하게 구현하는 능력도 요구하고 있다.

이동 방법을 살펴보면, 3R 이라면 오른쪽으로 3칸 이동하라는 의미가 이다. 단, 이동할 때 보드의 범위를 밖으로 나간다면, 반대쪽 첫 번째 칸으로 이동한다는 조건의 구현이 필요하다.

이동의 종료는 캐릭터가 방문했던 칸에 다시 방문하면 이동을 종료한다. 이때 캐릭터의 점수는 방문했던 칸의 개수를 알아내야 한다.

3) 문제 풀이 💡

구현 문제는 특별한 알고리즘을 요구하지 않는다. 우선, 게임의 규칙을 정확하게 파악할 필요가 있다.

  • 캐릭터는 현재 위치에서, 명령에 따라 <command> 방향으로 <count> 칸만큼 움직인다.
  • 캐릭터가 명령 수행 중에, 보드의 밖으로 이동할 경우, 반대편으로 이동한다.
  • 캐릭터가 이미 방문한 칸을 지나거나, 다시 방문하는 경우 게임은 끝난다.
  • 캐릭터가 방문한 칸의 개수가 게임에서 얻은 점수이다.

위의 요구 사항을 꼼꼼하게 구현할 수 있다면, 문제 자체는 어렵지 않게 해결할 수 있다.

4) 코드 💻

import java.util.*;

public class Main {

	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		int N = scanner.nextInt();
		int[] goormPos = {scanner.nextInt() - 1, scanner.nextInt() - 1};
		boolean[][] goormVisited = new boolean[N][N];
		int[] playerPos = {scanner.nextInt() - 1, scanner.nextInt() - 1};
		boolean[][] playerVisited = new boolean[N][N];

		String[][] board = new String[N][N];
		for (int i = 0; i < N; i++) {
			for (int j = 0; j < N; j++) {
				board[i][j] = scanner.next();
			}
		}

		int goormScore = move(goormPos, goormVisited, 1, board, N);
		int playerScore = move(playerPos, playerVisited, 1, board, N);

		if (goormScore > playerScore) {
			System.out.println("goorm " + goormScore);
		} else if (goormScore < playerScore) {
			System.out.println("player " + playerScore);
		}
		scanner.close();
	}

	public static int set_Pos(int a, int N) {
			if (a == -1) return N - 1;
			if (a == N) return 0;
			return a;
	}
	
	static HashMap<String, int[]> directions = new HashMap<String, int[]>() {
		{
			put("U", new int[]{-1, 0});
			put("D", new int[]{1, 0});
			put("L", new int[]{0, -1});
			put("R", new int[]{0, 1});
		}
	};

	public static int move(int[] pos, boolean[][] visited, int score, String[][] board, int N) {
			int x = pos[0];
			int y = pos[1];
			visited[x][y] = true;
			boolean flag = true;

			while (flag) {
					String command = board[x][y];
					int distance = Integer.parseInt(command.substring(0, command.length() - 1));
					String direction = command.substring(command.length() - 1);

					for (int i = 0; i < distance; i++) {
							x += directions.get(direction)[0];
							y += directions.get(direction)[1];
							x = set_Pos(x, N);
							y = set_Pos(y, N);

							if (!visited[x][y]) {
									visited[x][y] = true;
									score += 1;
							} else {
									flag = false;
									break;
							}
					}
			}
			return score;
	}

}

5) 코드 분석 🤔

  1. Import 문:

    import java.util.*;

    이 부분은 Java에서 제공하는 표준 라이브러리인 java.util 패키지에서 Scanner 클래스를 사용하기 위해 import하고 있다. Scanner 클래스는 표준 입력으로부터 데이터를 읽어올 때 사용된다.

  2. Main 클래스와 main 메서드:

    public class Main {
        public static void main(String[] args) {
            // 코드 내용
        }
    }

    Java 프로그램의 실행은 main 메서드부터 시작된다. public static void main(String[] args)는 프로그램의 진입점을 나타내며, 프로그램 실행 시 첫 번째로 호출되는 메서드이다.

  3. 변수 및 입력 처리:

    Scanner scanner = new Scanner(System.in);
    int N = scanner.nextInt();
    int[] goormPos = {scanner.nextInt() - 1, scanner.nextInt() - 1};
    boolean[][] goormVisited = new boolean[N][N];
    int[] playerPos = {scanner.nextInt() - 1, scanner.nextInt() - 1};
    boolean[][] playerVisited = new boolean[N][N];
    • scannerScanner 클래스의 객체로, 사용자 입력을 받기 위해 생성된다.
    • N은 게임 보드의 크기를 나타내는 변수로, scanner.nextInt()를 통해 입력받는다.
    • goormPosplayerPos는 각각 goorm 플레이어와 player 플레이어의 시작 위치를 나타낸다. scanner.nextInt() - 1을 통해 0-based 인덱스로 변환하여 입력받는다.
    • goormVisitedplayerVisited는 각 플레이어가 해당 위치를 방문했는지를 저장하는 2차원 배열이다.
  4. 보드 입력:

    String[][] board = new String[N][N];
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            board[i][j] = scanner.next();
        }
    }

    board는 게임 보드의 각 칸에 대한 정보를 저장하는 2차원 문자열 배열이다. 중첩된 루프를 사용하여 각 칸의 정보를 입력받는다.

  5. 움직임 관련 메서드:

    public static int set_Pos(int a, int N) {
        if (a == -1) return N - 1;
        if (a == N) return 0;
        return a;
    }
    
    static HashMap<String, int[]> directions = new HashMap<String, int[]>() {
        // HashMap 초기화 내용
    };
    
    public static int move(int[] pos, boolean[][] visited, int score, String[][] board, int N) {
        // move 메서드 내용
    }
    • set_Pos 메서드는 주어진 위치 a가 보드의 경계를 벗어나지 않도록 보정하는 역할을 한다.
    • directions는 방향 문자열과 해당 방향으로의 좌표 이동값을 매핑한 HashMap이다.
    • move 메서드는 플레이어의 움직임을 시뮬레이션하고 점수를 계산하는 핵심 로직을 담당한다.
  6. move 메서드 내용:

    int x = pos[0];
    int y = pos[1];
    visited[x][y] = true;
    boolean flag = true;
    
    while (flag) {
        // 명령을 해석하고 움직임 처리하는 로직
    }
    return score;
    • xy 변수는 현재 플레이어의 위치를 나타낸다.
    • 해당 위치를 방문했음을 표시한다.
    • flag 변수는 무한 루프를 관리하며, 루프 조건을 통해 움직임을 계속 처리하거나 중단한다.
    • 무한 루프 내에서는 현재 위치의 명령을 해석하여 주어진 방향과 거리만큼 이동하며 점수를 쌓거나 중단한다.
  7. 결과 출력:

    if (goormScore > playerScore) {
        System.out.println("goorm " + goormScore);
    } else if (goormScore < playerScore) {
        System.out.println("player " + playerScore);
    }
    scanner.close();

    두 플레이어의 점수를 비교하여 더 높은 점수를 가진 플레이어의 정보와 점수를 출력하고, 마지막으로 scanner를 닫아 입력 스트림을 종료한다.


이렇게 2주차 2번째 학습일기에는 코드 분석을 한 번 해보았다!
9일차 문제를 이틀동안 안 풀어 블록을 못 받은게 너무 아쉽다 😭😭

구름톤 챌린지가 뭔지 궁금하다면?
https://9oormthonchallenge.oopy.io/
학습 일기 작성법이 궁금하다면 ?
https://9oormthonchallenge.oopy.io/blogeventguide

profile
프로젝트를 통해 배운 개념이나 겪은 문제점들을 정리하고, 회고록을 작성하며 성장해나가는 곳입니다 😊

0개의 댓글