park의 위치를 문자열로 준것을 보고 2차원 배열을 이용하자 생각했고
routes의 문자열로 방향과 이동거리를 주는것을보고 문자열을 쪼갤때 많이 쓰는 <sstream>헤더를 활용하자 생각을 하였다.
또한 각 방향에 따라 수치들이 변경되는게 많아 define을 사용하여 매크로 상수화 했다.
(enum 쓰는게 가독성이 올라가는데 문제라서 그냥 define으로 하였다.)
이동 할떄 사용한 정보(경로)를 기록할 필요가 없어 전부 for 반복문 안에 지역변수로 활용하였다.
이 문제의 제일 중요한 것은 '강아지 이동'을 시킬때 조건 2가지가 중요하다
조건 1. 경계선이 벗어나면 다음 명령을 실행하고, 경계선 안에 있으면
조건 2. 이동 범위 안에 장애물이 있는지 확인을 하고 장애물이 있으면 다음 명령을 실행하게 해놨다.
조건1,조건2를 전부 만족할경우 현재 강아지의 좌표를 변경해주는 식으로 진행하였다.
간략한 내용은 플로우차트에 적어놨다.
플로우 차트 밑에 기능적으로 함수화를 하면 가독성이 많이 올라간다.
<플로우 차트>
0. 사전 준비
0-1. Park 지도를 만들기 (2차원 배열화)
0-1-1. Park 지도를 만들면서 (시작지점과 , 장애물지점을 설치)
(// 0:길 1:장애물 2:로봇강아지 )
1.routes 리스트의 data를 사용할수 있는 형식으로 만들기
1-1.방향(E,W,N,S) 와 이동거리(Move) 형식으로 만들기
2.강아지 진행시키기
(조건 1: 최종 위치기 경계선을 벗어나면 , 명령 동작x)
(조건 2: 이동경로에 장애물이 있는경우, 명령 동작x)
#include <string>
#include <vector>
#include <sstream>
#define UP_OR_LEFT -1
#define DOWN_OR_RIGHT 1
#define MOVE_X 1
#define MOVE_Y -1
#define PARK_ROAD 0
#define PARK_OBJECT 1
#define PARK_DOG 2
using namespace std;
vector<int> solution(vector<string> park, vector<string> routes)
{
vector<int> answer;
int width = park[0].length();
int height = park.size();
int dog_x =0, dog_y =0; // 로봇강아지 현재좌표
//0-1. Park 지도를 만들기 (2차원 배열화)
vector<vector<int>> Park_map(height,vector<int>(width,0));
//0-1-1. Park 지도를 만들면서 (시작지점과 , 장애물지점을 설치)
// (0:길 1:장애물 2:로봇강아지 )
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
//시작 지점 기록
if (park[y][x] == 'S')
{
dog_x = x;
dog_y = y;
Park_map[y][x] = 2;
}
//장애물 위치 기록
else if (park[y][x] == 'X')
{
Park_map[y][x] = 1;
}
}
}
int routes_roop = routes.size();
for (int route_index = 0; route_index < routes_roop; route_index++)
{
//1.routes 리스트의 data를 사용할수 있는 형식으로 만들기
// 1 - 1.방향(E, W, N, S) 와 이동거리(Move) 형식으로 만들기
char dir;
int move = 0;
stringstream stream;
stream.str(routes[route_index]);
stream >> dir;
stream >> move;
//------------------------------------------------------------
/* 2.강아지 진행시키기
(조건 1: 최종 위치기 경계선을 벗어나면 , 명령 동작x)
(조건 2: 이동경로에 장애물이 있는경우, 명령 동작x) */
int dir_add = 0; // 방향 이동시 -,+ 결정
int move_axis = 0; // 이동하는 축 결정
bool move_check = true;
switch (dir)
{
case 'E' :
dir_add = DOWN_OR_RIGHT;
move_axis = MOVE_X;
break;
case 'W':
dir_add = UP_OR_LEFT;
move_axis = MOVE_X;
break;
case 'S':
dir_add = DOWN_OR_RIGHT;
move_axis = MOVE_Y;
break;
case 'N':
dir_add = UP_OR_LEFT;
move_axis = MOVE_Y;
break;
}
int move_result = move * dir_add; //이동거리 * 방향결정 = 강아지가 움질익 방향
int move_min, move_max,move_tmp; // 이동 범위
switch (move_axis)
{
case MOVE_X:
//(조건 1: 최종 위치기 경계선을 벗어나면 , 명령 동작x)
if (dog_x + move_result >= width || dog_x + move_result < 0)
{
break;
}
//이동 범위 계산
move_min = dog_x;
move_max = dog_x + move_result;
if (move_min > move_max)
{
move_tmp = move_min;
move_min = move_max;
move_max = move_tmp;
}
//(조건 2: 이동경로에 장애물이 있는경우, 명령 동작x
for (int i = 0; i < move_max - move_min; i++)
{
int move_x = dog_x + (dir_add * (i + 1));
if (Park_map[dog_y][move_x] == PARK_OBJECT)
{
move_check = false;
break;
}
}
if (move_check)
{
Park_map[dog_y][dog_x] = PARK_ROAD;
dog_x += move_result;
Park_map[dog_y][dog_x] = PARK_DOG;
}
break;
case MOVE_Y:
//(조건 1: 최종 위치기 경계선을 벗어나면 , 명령 동작x)
if (dog_y + move_result >= height || dog_y + move_result < 0)
{
break;
}
//이동 범위 계산
move_min = dog_y;
move_max = dog_y + move_result;
if (move_min > move_max)
{
move_tmp = move_min;
move_min = move_max;
move_max = move_tmp;
}
//(조건 2: 이동경로에 장애물이 있는경우, 명령 동작x
for (int i = 0; i < move_max - move_min; i++)
{
int move_y = dog_y + (dir_add * (i + 1));
if (Park_map[move_y][dog_x] == PARK_OBJECT)
{
move_check = false;
break;
}
}
if (move_check)
{
Park_map[dog_y][dog_x] = PARK_ROAD;
dog_y += move_result;
Park_map[dog_y][dog_x] = PARK_DOG;
}
break;
}
}
answer.push_back(dog_y);
answer.push_back(dog_x);
return answer;
}