주사위 굴리기(Gold 4)
문제
접근법
문제에서 주어진 주사위의 기능들을 구현하여 시뮬레이션하는 문제입니다. 주사위의 이동 방향(1~4)을 받아서 동서남북으로 주사위를 굴리는 함수 Roll
을 구현하여서 해결할 수 있습니다. 주사위가 회전하는 부분은 4개의 면의 값을 변경하여 구현할 수 있습니다. 예를 들어 북쪽으로 이동하는 경우는 다음과 같습니다.
temp
=top
top
=left
left
=bottom
bottom
=right
right
=temp
같은 방식으로 다른 방향으로 이동도 구현할 수 있습니다. 이 문제에서 주의할 점은 시작점의 위치입니다. (x, y)로 제시된 주사위 위치를 x축 y축으로 착각하여 (2, 1)로 제시된 입력받고 행:1 열:2 로 계산하여 오답 처리된 경우가 많습니다. 문제에서는 첫 번째 값이 row에 해당하는 행이며, 두 번째 값이 col에 해당하는 열이라고 명시되어 있습니다. 반면, 어디에도 x, y가 x축 y축이라는 말은 없습니다. 이 점을 유의해서 구현해야 합니다.
전체 구현
#include <stdio.h>
#include <vector>
using namespace std;
using Level = vector<vector<int>>;
struct Pos {
Pos(int _r, int _c) : r(_r), c(_c) {}
Pos() {}
int r{};
int c{};
};
class Dice {
public:
Dice(Level& _level, Pos _pos);
int Roll(int dir);
private:
int top{};
int front{};
int left{};
int right{};
int back{};
int bottom{};
Level& level;
Pos pos;
const int MAX_R;
const int MAX_C;
bool East(); // 1
bool Weast(); // 2
bool North(); // 3
bool South(); // 4
void Stamp();
};
Dice::Dice(Level& _level, Pos _pos)
: level(_level), pos(_pos), MAX_R(level.size()) ,MAX_C(level[0].size()){
}
int Dice::Roll(int dir)
{
bool result{};
switch (dir)
{
case 1:
result = East();
break;
case 2:
result = Weast();
break;
case 3:
result = North();
break;
case 4:
result = South();
break;
}
if (result == false) return -1;
return top;
}
void Dice::Stamp()
{
int& cell = level[pos.r][pos.c];
if (cell == 0)
{
cell = bottom;
}
else
{
bottom = cell;
cell = 0;
}
}
bool Dice::East()
{
// 범위 체크
if (pos.c == MAX_C - 1) return false;
pos.c++;
int temp;
temp = top;
top = left;
left = bottom;
bottom = right;
right = temp;
Stamp();
return true;
}
bool Dice::Weast()
{
// 범위 체크
if (pos.c == 0) return false;
pos.c--;
int temp;
temp = top;
top = right;
right = bottom;
bottom = left;
left = temp;
Stamp();
return true;
}
bool Dice::North()
{
// 범위 체크
if (pos.r == 0) return false;
pos.r--;
int temp;
temp = top;
top = front;
front = bottom;
bottom = back;
back = temp;
Stamp();
return true;
}
bool Dice::South()
{
// 범위 체크
if (pos.r == MAX_R - 1) return false;
pos.r++;
int temp;
temp = top;
top = back;
back = bottom;
bottom = front;
front = temp;
Stamp();
return true;
}
int main() {
int N, M; // 세로 크기 N, 가로 크기 M (1 ≤ N, M ≤ 20)
scanf("%d %d ", &N, &M);
int r, c; // r c(0 ≤ r ≤ N-1, 0 ≤ c ≤ M-1)
scanf("%d %d ", &r, &c);
int K; // 명령의 개수 K (1 ≤ K ≤ 1,000)
scanf("%d ", &K);
// 레벨 생성 및 입력
Level level(N);
for (int i = 0; i < N; ++i)
{
level[i].resize(M);
for (int j = 0; j < M; ++j)
{
scanf("%d ", &level[i][j]);
}
}
// 주사위 생성
Dice dice(level, Pos(r, c));
while (K--)
{
int top;
int cmd;
scanf("%d ", &cmd);
top = dice.Roll(cmd);
if (top == -1)continue;
printf("%d\n", top);
}
return 0;
}