각 면의 칸의 index는 이렇게 설정했다. ( 실제론 0~8 이므로 1씩 빼줘야함 )
아랫면만 반대로 한 이유는 어쩌다 보니 이렇게 하는게 더 편했다.
이렇게 해서 각각의 회전을 처리하면 된다.
즉 큐브를 한번 돌리면 해당 면을 돌릴 때 돌아갈 4개의 면의 칸3개가 정해져있고 이 칸들을 방향에 맞게 돌리고, 돌리는 해당 면의 내부 칸들을 방향에 맞게 90도 돌리면 된다.
이 때 아랫면은 반대로 했기 때문에 아랫면의 내부를 돌릴 땐 반대로 돌린다.
SelectedLine
클래스를 만들어 사용했다.tmp
에 넣어 놓고 방향에 맞게 돌려서 cube
에 넣는다.import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.StringTokenizer;
public class Main {
/* 회전에서 돌아갈 줄의 내용을 담고 있는 클래스
* position : 돌아갈 면의 위치
* line : 해당 면에서 돌아갈 칸의 위치 3개
*/
private static class SelectedLine {
int position;
int[] line;
public SelectedLine(int position, int[] line) {
this.position = position;
this.line = line;
}
}
/*
* 복잡한 구현 문제이다.
* 회전이 일어날 때 정해진 면의 칸들을 방향에 맞게 이동시키고 회전하는 면의 모든 칸을 방향에 따라 회전시킨다.
*/
public static void main(String[] args) throws IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));
int T = Integer.parseInt(in.readLine());
for (int t = 0; t < T; t++) {
int n = Integer.parseInt(in.readLine());
StringTokenizer st = new StringTokenizer(in.readLine());
// 큐브의 초기 값들 순서대로 위, 아래, 앞, 뒤, 왼쪽, 오른쪽
char[][] cube = { { 'w', 'w', 'w', 'w', 'w', 'w', 'w', 'w', 'w' }, // U
{ 'y', 'y', 'y', 'y', 'y', 'y', 'y', 'y', 'y' }, // D
{ 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r' }, // F
{ 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o' }, // B
{ 'g', 'g', 'g', 'g', 'g', 'g', 'g', 'g', 'g' }, // L
{ 'b', 'b', 'b', 'b', 'b', 'b', 'b', 'b', 'b' } // R
};
// 들어오는 명령어에 맞게 회전하는 함수와 해당 면을 돌리는 함수를 실행한다.
for (int i = 0; i < n; i++) {
String rotaion = st.nextToken();
char p = rotaion.charAt(0);
boolean clock = rotaion.charAt(1) == '+';
switch (p) {
case 'U':
U(clock, cube);
break;
case 'D':
D(clock, cube);
break;
case 'F':
F(clock, cube);
break;
case 'B':
B(clock, cube);
break;
case 'L':
L(clock, cube);
break;
case 'R':
R(clock, cube);
break;
}
lotateSquare(cube, p, clock);
}
// 모든 명령어를 수행한 후 윗면의 내용을 출력한다.
for (int i = 0; i < 9; i++) {
out.write(cube[0][i]);
if ((i + 1) % 3 == 0)
out.write("\n");
}
}
out.flush();
}
// 윗면을 돌릴때 앞, 오른쪽, 뒤, 왼쪽의 위쪽 칸을 돌린다.
private static void U(boolean clock, char[][] cube) {
// 앞, 오른쪽, 뒤, 왼쪽
// 각면의 위쪽에 해당하는 칸의 index를 가져온다.
SelectedLine[] lines = new SelectedLine[4];
lines[0] = new SelectedLine(2, new int[] {0, 1, 2});
lines[1] = new SelectedLine(5, new int[] {6, 3, 0});
lines[2] = new SelectedLine(3, new int[] {8, 7, 6});
lines[3] = new SelectedLine(4, new int[] {2, 5, 8});
rotation(cube, lines, clock);
}
// 아랫면을 돌릴때 앞, 오른쪽, 뒤, 왼쪽의 위쪽 칸을 돌린다.
private static void D(boolean clock, char[][] cube) {
// 앞, 왼쪽, 뒤, 오른쪽
// 각면의 아래쪽에 해당하는 칸의 index를 가져온다.
SelectedLine[] lines = new SelectedLine[4];
lines[0] = new SelectedLine(2, new int[] {6, 7, 8});
lines[1] = new SelectedLine(4, new int[] {0, 3, 6});
lines[2] = new SelectedLine(3, new int[] {2, 1, 0});
lines[3] = new SelectedLine(5, new int[] {8, 5, 2});
rotation(cube, lines, clock);
}
// 앞면을 돌릴때 위, 왼쪽, 아래, 오른쪽의 앞쪽 칸을 돌린다.
private static void F(boolean clock, char[][] cube) {
// 위, 왼쪽, 아래, 오른쪽
// 각면의 앞쪽에 해당하는 칸의 index를 가져온다.
SelectedLine[] lines = new SelectedLine[4];
lines[0] = new SelectedLine(0, new int[] {6, 7, 8});
lines[1] = new SelectedLine(4, new int[] {6, 7, 8});
lines[2] = new SelectedLine(1, new int[] {8, 7, 6});
lines[3] = new SelectedLine(5, new int[] {6, 7, 8});
rotation(cube, lines, clock);
}
// 뒷면을 돌릴때 위, 왼쪽, 아래, 오른쪽의 뒤쪽 칸을 돌린다.
private static void B(boolean clock, char[][] cube) {
// 위, 오른쪽, 아래, 왼쪽
// 각면의 뒷쪽에 해당하는 칸의 index를 가져온다.
SelectedLine[] lines = new SelectedLine[4];
lines[0] = new SelectedLine(0, new int[] {0, 1, 2});
lines[1] = new SelectedLine(5, new int[] {0, 1, 2});
lines[2] = new SelectedLine(1, new int[] {2, 1, 0});
lines[3] = new SelectedLine(4, new int[] {0, 1, 2});
rotation(cube, lines, clock);
}
// 오른쪽면을 돌릴때 앞, 아래, 뒤, 위의 오른쪽 칸을 돌린다.
private static void R(boolean clock, char[][] cube) {
// 앞, 아래, 뒤, 위
// 각면의 오른쪽에 해당하는 칸의 index를 가져온다.
SelectedLine[] lines = new SelectedLine[4];
lines[0] = new SelectedLine(2, new int[] {2, 5, 8});
lines[1] = new SelectedLine(1, new int[] {8, 5, 2});
lines[2] = new SelectedLine(3, new int[] {2, 5, 8});
lines[3] = new SelectedLine(0, new int[] {2, 5, 8});
rotation(cube, lines, clock);
}
// 왼쪽면을 돌릴때 앞, 아래, 뒤, 위의 오른쪽 칸을 돌린다.
private static void L(boolean clock, char[][] cube) {
// 앞, 위, 뒤, 아래
// 각면의 왼쪽에 해당하는 칸의 index를 가져온다.
SelectedLine[] lines = new SelectedLine[4];
lines[0] = new SelectedLine(2, new int[] {0, 3, 6});
lines[1] = new SelectedLine(0, new int[] {0, 3, 6});
lines[2] = new SelectedLine(3, new int[] {0, 3, 6});
lines[3] = new SelectedLine(1, new int[] {6, 3, 0});
rotation(cube, lines, clock);
}
// 칸들을 돌려 cube에 저장하는 함수
private static void rotation(char[][] cube, SelectedLine[] lines, boolean clock) {
char[][] tmp = new char[4][];
// 시계방향이면 다음 순서의 내용을 이전 lines에 넣는다.
// 넣기전 tmp 에 값들을 순서대로 저쟁해놓음
if (clock) {
for (int i = 0; i < 3; i++) {
tmp[i] = getLine(cube, lines[i + 1]);
}
tmp[3] = getLine(cube, lines[0]);
}
else {
for (int i = 1; i < 4; i++) {
tmp[i] = getLine(cube, lines[i - 1]);
}
tmp[0] = getLine(cube, lines[3]);
}
// 저장된 값을 cube에 적용
for (int i = 0; i < 4; i++) {
setLine(cube, lines[i], tmp[i]);
}
}
// selectedLine에 존재하는 면과 칸들의 index 정보를 토대로 실제 값들을 가진 result를 리턴한다.
private static char[] getLine(char[][] cube, SelectedLine selectedLine) {
char[] result = new char[3];
int p = selectedLine.position;
int[] line = selectedLine.line;
for(int i = 0; i < 3; i++)
result[i] = cube[p][line[i]];
return result;
}
// selectedLine에 존재하는 면과 칸들의 index 위치에 tmp에 해당하는 값을 넣어준다.
private static void setLine(char[][] cube, SelectedLine selectedLine, char[] tmp) {
int p = selectedLine.position;
int[] line = selectedLine.line;
for(int i = 0; i < 3; i++)
cube[p][line[i]] = tmp[i];
}
// 해당 면을 방향대로 돌리는 함수, 단 아랫면은 반대로 돌린다 -> 아랫면은 오른쪽 왼쪽을 바꾸어서 사용했기 때문
private static void lotateSquare(char[][] cube, char p, boolean clock) {
char[] tmp = new char[9];
int position = -1;
switch (p) {
case 'U':
position = 0;
break;
case 'D':
position = 1;
clock = !clock;
break;
case 'F':
position = 2;
break;
case 'B':
position = 3;
break;
case 'L':
position = 4;
break;
case 'R':
position = 5;
break;
}
if(!clock) {
int cnt = 0;
for(int i = 2; i >= 0; i--) {
for(int j = 0; j < 3; j++) {
tmp[cnt++] = cube[position][i+ (j*3)];
}
}
}
else {
int cnt = 0;
for(int i = 6; i <= 8; i++) {
for(int j = 0; j < 3; j++) {
tmp[cnt++] = cube[position][i - (j*3)];
}
}
}
cube[position] = tmp;
}
}