[Baekjoon,3190]뱀
해결
이 문제는 위와 같은 이미지의 게임을 구현하면 되는 문제이다. 구현해야 할 부분은 아래와 같다.
- 뱀을 객체로 표현
- 변수: 현재 상태
- 위치
- 방향
- 꼬리의 위치
- 함수: 다음으로 한 칸 움직임
- 벽 또는 몸에 부딪힘, 사과를 먹는 행위 표현
- 함수: 방향 전환
- 변수: 현재 상태
코드의 간결화를 위해 +=, == 연산자를 오버로딩 하였으며 움직임 정보가 순서대로 주어지기 때문에 queue에 저장했다. 또한 방향을 전환하는 행위를 상수 배열을 이용하였고 각 방향에 대해 1을 더하거나 빼면 방향 전환을 할 수 있도록 했다. move 함수는 다음 움직임이 실패로 돌아가는 경우 false를 반환하였다.
사과를 먹는 것은 queue를 이용하여 쉽게 표현했다. 사과를 못 먹으면 새로운 위치의 큐를 추가하고 꼬리의 큐를 pop하는 식이다.
구현
구현 할 때 주의사항은 사과의 좌표가 [1,1]을 기준으로 주어지는 것을 유념해야 한다는 것이다.
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
enum{ UP=0, RIGHT, DOWN, LEFT };
const int dx[4]={0,1,0,-1};
const int dy[4]={-1,0,1,0};
int N,COUNT=0;
class Pos
{
private:
int y,x;
public:
Pos(int _y=0, int _x=0) : y(_y), x(_x) {}
bool operator==(const Pos& a) const
{
return (a.x==x) && (a.y==y);
}
Pos& operator+=(const Pos& a)
{
y+=a.y;
x+=a.x;
return *this;
}
bool inRange()
{
return 0<=x && x<N && 0<=y && y<N;
}
};
// <사과 위치, 존재 여부>
vector<pair<Pos,bool> > applesPos;
class Snake
{
private:
Pos pos;
int dir;
queue<Pos> tail;
public:
Snake() : pos(), dir(RIGHT)
{
tail.push(Pos());
}
// 방향을 바꾼다.
void turn(char ch)
{
// 왼쪽으로 회전
if(ch=='L')
{
if(--dir==-1)
dir=LEFT;
}
else if(ch=='D')
{
if(++dir==4)
dir=UP;
}
}
// 현재 방향으로 이동하는 데 범위를 벗어나거나 몸에 부딪힌 경우 false를 반환한다.
bool move()
{
++COUNT;
Pos nextPos(dy[dir],dx[dir]);
nextPos+=pos;
if(!nextPos.inRange())
return false;
// 몸에 부딪히는 지 확인
bool isHited=false;
int size=tail.size();
while(size--)
{
Pos slicePos=tail.front();
tail.pop();
if(nextPos==slicePos)
isHited=true;
tail.push(slicePos);
}
if(isHited)
return false;
bool canEat=false;
// 사과를 먹은 경우 확인한다.
for(int i=0;i<applesPos.size();++i)
if(applesPos[i].second && applesPos[i].first==nextPos)
{
applesPos[i].second=false;
canEat=true;
break;
}
tail.push(nextPos);
// 사과를 못 먹은 경우
if(!canEat)
tail.pop();
pos+=Pos(dy[dir],dx[dir]);
return true;
}
};
int main()
{
int appleNum;
cin>>N>>appleNum;
for(int i=0;i<appleNum;++i)
{
int y,x;
cin>>y>>x;
applesPos.push_back(make_pair(Pos(y-1,x-1),true));
}
// 움직임 정보
queue<pair<int,char> > moveInfo;
int moveNum;
cin>>moveNum;
for(int i=0;i<moveNum;++i)
{
int at;
char dir;
cin>>at>>dir;
moveInfo.push(make_pair(at,dir));
}
// 시뮬레이션을 돌린다.
Snake snake;
while(snake.move())
if(moveInfo.front().first==COUNT)
{
snake.turn(moveInfo.front().second);
moveInfo.pop();
}
cout<<COUNT<<endl;
return 0;
}
댓글남기기