-
[구현] 문제이름 : 게임 개발Algorithm/유형별 문제 풀기 2021. 6. 30. 12:20
문제 설명
게임 캐릭터가 맵 안에서 움직이는 시스템을 개발 중이다. 캐릭터가 있는 장소는 1 x 1 크기의 정사각형으로 이루어진 N x M 크기의 직사각형으로, 각각의 칸은 육지 또는 바다이다. 캐릭터는 동성남북 중 한 곳을 바라본다. 캐릭터는 상하좌우로 움직일 수 있고, 바다로 되어 있는 공간에는 갈 수 없다. 캐릭터의 움직임을 설정하기 위해 정해 놓은 메뉴얼은 다음과 같다.
1. 현재 위치에서 현재 방향을 기준으로 왼쪽 방향 부터 차례대로 갈 곳을 정한다.
2. 캐릭터의 바로 왼쪽 방향에 아직 가보지 않은 칸이 존재한다면, 왼쪽 방향으로 회전한 다음 왼쪽으로 한 칸 전진한다. 왼쪽 방향에 가보지 않은 칸이 없다면, 왼쪽 방향으로 회전만 수행하고 1단계로 돌아간다.
3 만약 네 방향 모두 이미 가본 칸이거나 바다로 되어 있는 칸인 경우에는, 바라보는 방향을 유지한 채로 한 칸 뒤로 가고 1단계로 돌아간다. 단 이때 뒤쪽 방향이 바다인 칸이라 뒤로 갈 수 없는 경우에는 움직임을 멈춘다.
위 과정을 반복적으로 수행하면서 캐릭터가 방문한 칸의 수 출력하는 프로그램 작성하기
1. 사용 알고리즘
구현
2. 문제 해결 아이디어
전형적인 시뮬레이션 문제이고, 문제에서 요구하는 내용을 오류 없이 구현해내는 것이 중요함
중요한 부분은 방향(direction)을 설정해서 이동하는 문제 유형에서는 dx, dy라는 별도의 리스트를 만들어 방향을 정하는 것이 효과적임
: 각 방향에 대해 이동 거리를 미리 저장해두기 -> 반복문을 이용해 모든 방향을 차례대로 확인 가능함, 접근 가능함
3. 코드
구현방식)
1. int dx[], int dy[]을 사용해 북, 동, 남, 서 방향을 향한 이동거리를 저장해 둠
-> 어느 방향에서나 움직이는 거리는 동일하니까
-> 문제에서 0 : 북, 1 : 동, 2 : 남, 3 : 서 로 설정했으므로 바라보는 방향에 따라 이동거리를 배열의 index로 접근 가능함
2. nx, ny 변수로 사용자의 이동 후 위치를 저장하고 조건에 부합하는지 우선적으로 확인함
-> nx = x + dx[lookAt]; ny = y + dy[lookAt];
3. while문 내에서 문제에서 주어진 게임의 조건에 맞게 순차적으로 설계함
import java.util.Scanner; public class Main { public static int lookAt; public static void turnLeft() { //개선2 lookAt -= 1; if(lookAt == -1) lookAt = 3; //북 -> 서 방향 전환 시 } public static void main(String[] args) { Scanner kbd = new Scanner(System.in); int N, M; //직사각형 크기 int x, y; //사용자 위치 N = kbd.nextInt(); M = kbd.nextInt(); x = kbd.nextInt(); y = kbd.nextInt(); lookAt = kbd.nextInt(); //바라보고 있는 방향 int gameBoard[][] = new int[N][M]; //게임맵 for(int i = 0; i < N; i++) for(int j = 0; j < M; j++) gameBoard[i][j] = kbd.nextInt(); //직관적으로 변수명 표현 ! int visited = 2; int ocean = 1; int land = 0; gameBoard[x][y] = visited; //현재 사용자 위치 방문했다고 표시 //북 동 남 서에 따른 이동 거리 -> 개선1 int dx[] = {-1, 0, 1, 0}; int dy[] = {0, 1, 0, -1}; int moveCount = 0; int turnTime = 0; //게임 룰 순서대로 처리해주기 while(true) { //1. 왼쪽 회전 turnLeft(); int nx = x + dx[lookAt]; int ny = y + dy[lookAt]; //2-1. 회전 이후 정면에 가보지 않은 칸이 존재하는 경우 if(gameBoard[nx][ny] == land) { gameBoard[nx][ny] = visited; //방문 표시 x = nx; //사용자 위치 업데이트 y = ny; moveCount++; turnTime = 0; continue; //밑의 조건들 확인 필요 없으니까 } //2-2. 회전 이후 정면에 가보지 않은 칸이 없거나 바다인 경우 else turnTime++; //3. 네 방향 모두 갈 수 없는 경우 if(turnTime == 4) { nx = x - dx[lookAt]; ny = y - dx[lookAt]; //뒤로 갈 수 있는 경우 뒤로 이동하기 if(gameBoard[nx][ny] != ocean) { x = nx; //사용자 위치 업데이트 y = ny; moveCount++; } //뒤가 바다인 경우 이동 불가 else break; turnTime = 0; //회전 횟수 초기화 } } System.out.println(moveCount); } }
추가 !
클린코드에서 읽은 대로 변수명을 직관적으로 표현했더니 코드를 작성할 때 헷갈리지 않았다. visited, ocean, land, gameBoard 등등 앞으로 더욱 신경써야겠다.
'Algorithm > 유형별 문제 풀기' 카테고리의 다른 글
[DFS/BFS] 문제 이름 : 미로 탈출 (0) 2021.07.08 [DFS/BFS] 문제이름 : 음료수 얼려 먹기 (0) 2021.07.05 [구현] 문제 이름 : 왕실의 나이트 (0) 2021.06.29 [구현] 문제 이름 : 시각 (0) 2021.06.29 [그리디] 1이 될 때까지 (0) 2021.06.26