[卵の仮面]実現-<3>ゲーム開発


💡 問題の説明


ヘミンはゲームキャラクターが地図を移動するシステムを開発している.キャラクタの位置は1 x 1サイズの正方形からなるNxMサイズの矩形で、各格子は陸地または海洋です.キャラクターは東西南北から一つの場所を眺めている.
地図上の各格子は(A,B)で表すことができ、Aは北から来た格子の個数、Bは西から来た格子の個数である.キャラクターは上下左右に移動でき、海の空間に入ることはできません.
キャラクターの動きを設定するためのメニューはこうです.
  • 現在位置で、現在方向を基準として左方向(反時計回り方向90度回転)から順に行き先を決めます.
  • のキャラクターの真左にまだ行ったことのない格子がある場合は、左に回転して左に1格進みます.左方向に未通過の格子がない場合は左方向のみ回転し、第1段階に戻る.
  • 4 4方向が既に行ったものや海の格子であれば、眺める方向を保ち、1段後ろに1段後ろに進み、1段目に戻ります.しかし、このとき後ろの方向が海の格子になっていて、後ろに進めないと移動が止まってしまいます.
  • ヘミンはこのような過程を繰り返し、キャラクターの移動に異常があるかどうかをテストしようとした.メニューに従ってロールを移動した後、ロールがアクセスするセル数を出力するプログラムを作成します.

    💡 入力例

    4 4		// 4 x 4 맵 생성
    1 1 0	//  (1, 1)에 북쪽(0)을 바라보고 서 있는 캐릭터
    1 1 1 1	// 첫 줄은 모두 바다
    1 0 0 1	// 둘째 줄은 바다/육지/육지/바다
    1 1 0 1	// 셋째 줄은 바다/바다/육지/바다
    1 1 1 1	// 넷째 주른 모두 바다
  • の最初の行に、スペースで区切られた一覧の縦サイズNと横サイズMを入力します.
  • の2行目には、ゲームキャラクターが存在するセルの座標(A,B)と望向(北、東、南、西の順に0,1,2,3)が与えられる.
  • の3行目から地図が陸地なのか海なのかの情報が提供されます.(0:陸地、1:海)
  • 💡 出力例

    3

    💡 ソリューションのアイデア&私の答え


    アクセス先を保存するためのレイアウトと、指定した地図情報を格納するための2 Dレイアウトを宣言し、シミュレーションを行い、指定したマニュアルに従ってキャラクタを移動します.この場合、一般的に方向を設定して移動する問題のタイプについては、dx、dyという個別のリストを作成して方向を決定することが望ましい.
    package SuHyeon;
    
    import java.util.Scanner;
    
    public class GameDev {
    
        public static int n, m, x, y, d;
        // 방문 기록 저장을 위한 맵 0으로 초기화 (가보지 않은 곳 체크용)
        public static int[][] visited = new int[50][50];
        // 현재 맵 정조 기록하기 위한 변수 선언
        public static int[][] map = new int[50][50];
        // 북, 동, 남, 서 방향을 바라복 있을 때 이동 정의
        public static int[] dx = {-1, 0, 1, 0};
        public static int[] dy = {0, 1, 0, -1};
    
        /**
         * 왼쪽으로 회전 시
         * 동 ->  북, 남 -> 동, 서 -> 남, 북 -> 서
         * 즉 방향이 1씩 감소하게 됨
         */
        public static void turn_left() {
            d--;
            if (d == -1) d = 3;
        }
    
        public static void main(String[] args) {
            // n, m값 입력 받기
            Scanner sc = new Scanner(System.in);
            n = sc.nextInt(); m = sc.nextInt();
    
            // 현재 좌표(x, y)와 바라보는 방향(d) 입력 받기
            x = sc.nextInt(); y = sc.nextInt(); d = sc.nextInt();
            // 현재 좌표 방문 처리
            visited[x][y] = 1;
    
            // 현재 맵 정보 입력 받기
            for(int i=0; i<n; i++)  {
                for(int j=0; j<m; j++) {
                    map[i][j] = sc.nextInt();
                }
            }
    
            // 시뮬레이션 시작
            int result = 1; // 현재 방문한 칸의 수 포함
            int turn_time = 0; // 회전한 횟수가 4번일 경우 뒤로 한 칸 이동해야 함
    
            while(true) {
                turn_left(); // 1단계 왼쪽으로 회전
                int nx = x + dx[d];
                int ny = y + dy[d];
                // 회전한 이후 정면에 가보지 않은 칸이 존재하면서 육지인 경우 이동
                if(visited[nx][ny] == 0 && map[nx][ny] == 0) {
                    visited[nx][ny] = 1; // 이동한 칸을 방문했음 표시
                    result++;
                    x = nx;
                    y = ny;
                    turn_time = 0;
                    continue;
                }
                else { // 회전한 이후 정면에 가본 칸이거나 바다인 경우
                    turn_time++;
                }
    
                // 네 방향을모두 갈 수 없는 경우
                if(turn_time == 4) {
                    nx = x - dx[d];
                    ny = y - dy[d];
                    // 뒤로 갈 수 있는 경우 (즉, 육지인 경우)
                    if(map[nx][ny] == 0) {
                        x = nx;
                        y = ny;
                        turn_time = 0;
                    }
                    else { // 뒤로 갈 수 없는 경우 종료
                        break;
                    }
                }
            }
    
            System.out.println(result);
            sc.close();
        }
    }
    

    💡 サンプル回答

    import java.util.*;
    
    public class Main {
    
        public static int n, m, x, y, direction;
        // 방문한 위치를 저장하기 위한 맵을 생성하여 0으로 초기화
        public static int[][] d = new int[50][50];
        // 전체 맵 정보
        public static int[][] arr = new int [50][50];
    
        // 북, 동, 남, 서 방향 정의
        public static int dx[] = {-1, 0, 1, 0};
        public static int dy[] = {0, 1, 0, -1};
    
        // 왼쪽으로 회전
        public static void turn_left() {
            direction -= 1;
            if (direction == -1) direction = 3;
        }
    
        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
    
            // N, M을 공백을 기준으로 구분하여 입력받기
            n = sc.nextInt();
            m = sc.nextInt();
            
            // 현재 캐릭터의 X 좌표, Y 좌표, 방향을 입력받기
            x = sc.nextInt();
            y = sc.nextInt();
            direction = sc.nextInt();
            d[x][y] = 1; // 현재 좌표 방문 처리
    
            // 전체 맵 정보를 입력 받기
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < m; j++) {
                    arr[i][j] = sc.nextInt();
                }
            }
    
            // 시뮬레이션 시작
            int cnt = 1;
            int turn_time = 0;
            while (true) {
                // 왼쪽으로 회전
                turn_left();
                int nx = x + dx[direction];
                int ny = y + dy[direction];
                // 회전한 이후 정면에 가보지 않은 칸이 존재하는 경우 이동
                if (d[nx][ny] == 0 && arr[nx][ny] == 0) {
                    d[nx][ny] = 1;
                    x = nx;
                    y = ny;
                    cnt += 1;
                    turn_time = 0;
                    continue;
                }
                // 회전한 이후 정면에 가보지 않은 칸이 없거나 바다인 경우
                else turn_time += 1;
                // 네 방향 모두 갈 수 없는 경우
                if (turn_time == 4) {
                    nx = x - dx[direction];
                    ny = y - dy[direction];
                    // 뒤로 갈 수 있다면 이동하기
                    if (arr[nx][ny] == 0) {
                        x = nx;
                        y = ny;
                    }
                    // 뒤가 바다로 막혀있는 경우
                    else break;
                    turn_time = 0;
                }
            }
    
            System.out.println(cnt);
        }
    
    }
    *ソース:https://github.com/ndb796/python-for-coding-test