B B B
B B B
B B B
W W W O O O G G G Y Y Y
W W W O O O G G G Y Y Y
W W W O O O G G G Y Y Y
R R R
R R R
R R R
(초기 상태 출력)
CUBE> FRR'U2R
F
(큐브상태)
R
(큐브상태)
...
R
(큐브상태)
CUBE> Q
경과시간: 00:31 //추가 구현 항목
조작갯수: 6
이용해주셔서 감사합니다. 뚜뚜뚜.
function main() {
for() { // 들여쓰기 1단계
if() { // 들여쓰기 2단계
return; // 들여쓰기 3단계
}
}
}
프롬프트를 실행하는 Main class와 Prompt 관련 메서드를 저장하는 Prompt class, 큐브에 관련된 정보와 push 메서드들이 들어있는 Cube class를 구현하였다.
프로그램 종료 시 경과 시간 출력
기능을 구현했다. static long startTime, endTime, totalTime;
public static void main(String[] args) {
startTime = System.nanoTime();
Prompt p = new Prompt();
p.runPrompt();
endTime = System.nanoTime();
totalTime = endTime - startTime;
double seconds = (double) totalTime / 1_000_000_000.0;
long t = Math.round(seconds);
System.out.printf("경과시간: %02d:%02d\n", t / 60, t % 60);
System.out.println("조작갯수: " + Cube.count);
System.out.println("이용해주셔서 감사합니다. 뚜뚜뚜.");
}
메서드 | 기능 |
---|---|
getCommandKeyList(scanner) | 사용자로부터 입력받은 명령어를 저장하는 cmdQueue를 ArrayList의 형태로 반환 |
isInteger(cmd) | 문자열 cmd를 정수로 변환할 수 있을 경우 true, 변환이 불가능할 경우 false 반환 |
selectCommand(cube, cmdQueue) | cmdQueue의 명령어를 차례로 실행 |
runPrompt() | 간단한 프롬프트 출력 및 사용자의 입력을 바탕으로 프로그램 실행 |
getCommandKeyList 메서드 : 사용자로부터 입력받은 명령어를 저장하는 cmdQueue를 ArrayList의 형태로 반환
isInteger 메서드 : 문자열 cmd를 정수로 변환할 수 있을 경우 true, 변환이 불가능할 경우 false 반환
ArrayList<String> getCommandKeyList(Scanner sc) {
String cmd = sc.nextLine();
ArrayList<String> cmdQueue = new ArrayList<>();
int countSingleQuote = 0;
for (int i = 0; i < cmd.length(); i++) {
String cmdKey = Character.toString(cmd.charAt(i)).toUpperCase();
if (cmdKey.equals("'")) {
countSingleQuote++;
cmdQueue.set(i - countSingleQuote, cmdQueue.get(i - countSingleQuote) + "'");
continue;
}
int n = 0;
if (isInteger(cmdKey)) n = Integer.parseInt(cmdKey);
for (int j = 0; j < n - 1; j++) {
cmdQueue.add(cmdQueue.get(i - 1 - countSingleQuote));
}
if (!isInteger(cmdKey)) cmdQueue.add(cmdKey);
}
return cmdQueue;
}
selectCommand 메서드 : cmdQueue의 명령어를 차례로 실행
void selectCommand(Cube cube, ArrayList<String> cmdQueue) {
for (String x : cmdQueue) {
if (x.equals("S")) {
System.out.println("\nNewly Scrambled Rubik's Cube");
cube.scrambleCube();
cube.printRubiksCube();
break;
}
if (x.equals("Q")) {
isLoop = false;
break;
}
System.out.println("\n" + x);
cube.rotateCube(x);
cube.printRubiksCube();
}
}
runPrompt 메서드 : 간단한 프롬프트 출력 및 사용자의 입력을 바탕으로 프로그램 실행
void runPrompt() {
Cube cube = new Cube();
cube.printRubiksCube();
Scanner sc = new Scanner(System.in);
while (isLoop) {
System.out.print("\n" + PROMPT);
selectCommand(cube, getCommandKeyList(sc));
if(cube.checkAnswer()) {
System.out.println("\n🎉 정답입니다. 축하드립니다. 뚜뚜뚜.");
isLoop = false;
}
}
sc.close();
}
String[][] cubeLeft, cubeFront, cubeRight, cubeUp, cubeBack, cubeDown;
private final String[] COMMAND_KEYS = { "L", "L'", "R", "R'", "U", "U'", "D", "D'", "F", "F'", "B", "B'" };
static int count = 0;
public Cube() {
cubeLeft = new String[3][3];
cubeFront = new String[3][3];
cubeRight = new String[3][3];
cubeUp = new String[3][3];
cubeBack = new String[3][3];
cubeDown = new String[3][3];
initCube();
}
메서드 | 기능 |
---|---|
initCube() | 큐브를 다 맞춰진 상태로 초기화 |
scrambleCube() | 큐브를 무작위로 섞기 |
checkAnswer() | 큐브가 완전히 맞춰졌다면 true, 아니라면 false를 반환 |
rotateCube(cmd) | 명령어 문자열에 따라 회전 메서드를 실행 |
rotateClockwise(cubeC) | 큐브의 한 면을 시계 방향으로 회전 |
rotateCounterclockwise(cubeC) | 큐브의 한 면을 시계 반대 방향으로 회전 |
rotateFront(cmd) | 큐브의 앞면을 90도 회전 |
rotateBack(cmd) | 큐브의 뒷면을 90도 회전 |
rotateLeft(cmd) | 큐브의 왼쪽 면을 90도 회전 |
rotateRight(cmd) | 큐브의 오른쪽 면을 90도 회전 |
rotateUp(cmd) | 큐브의 윗면을 90도 회전 |
rotateDown(cmd) | 큐브의 바닥을 90도 회전 |
printRubiksCube() | 큐브의 6면을 2차원으로 펼쳐진 상태로 출력 |
initCube 메서드 : 큐브를 다 맞춰진 상태로 초기화
2차원 배열로 선언된 큐브의 6개 면을 각각 다른 색상으로 초기화해 주었다.
void initCube() {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
cubeLeft[i][j] = "W";
cubeFront[i][j] = "O";
cubeRight[i][j] = "G";
cubeBack[i][j] = "Y";
cubeUp[i][j] = "B";
cubeDown[i][j] = "R";
}
}
}
scrambleCube 메서드 : 큐브를 무작위로 섞기
private final String[] COMMAND_KEYS = { "L", "L'", "R", "R'", "U", "U'", "D", "D'", "F", "F'", "B", "B'" };
void scrambleCube() {
for (int i = 0; i < 30; i++) {
int randomNum = ThreadLocalRandom.current().nextInt(0, 12);
rotateCube(COMMAND_KEYS[randomNum]);
}
}
checkAnswer : 큐브가 완전히 맞춰졌다면 true, 아니라면 false를 반환
boolean checkAnswer() {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (cubeLeft[i][j].equals("W")==false) return false;
if (cubeFront[i][j].equals("O")==false) return false;
if (cubeRight[i][j].equals("G")==false) return false;
if (cubeBack[i][j].equals("Y")==false) return false;
if (cubeUp[i][j].equals("B")==false) return false;
if (cubeDown[i][j].equals("R")==false) return false;
}
}
return true;
}
rotateCube 메서드 : 명령어 문자열에 따라 회전 메서드를 실행
step-2에서와 마찬가지로, rotateCube 메서드가 실행될 때마다 cmd 문자열을 키로 갖고있는 메서드가 실행된다.
void rotateCube(String cmd) {
Map<String, Runnable> commands = new HashMap<>();
commands.put("L", () -> rotateLeft("L"));
commands.put("L'", () -> rotateLeft("L'"));
commands.put("R", () -> rotateRight("R"));
commands.put("R'", () -> rotateRight("R'"));
commands.put("U", () -> rotateUp("U"));
commands.put("U'", () -> rotateUp("U'"));
commands.put("D", () -> rotateDown("D"));
commands.put("D'", () -> rotateDown("D'"));
commands.put("F", () -> rotateFront("F"));
commands.put("F'", () -> rotateFront("F'"));
commands.put("B", () -> rotateBack("B"));
commands.put("B'", () -> rotateBack("B'"));
commands.get(cmd).run();
}
rotateClockwise 메서드 : 큐브의 한 면을 시계 방향으로 회전
rotateCounterclockwise 메서드 : 큐브의 한 면을 시계 반대 방향으로 회전
String[][] rotateClockwise(String[][] cubeC) {
String[][] updatedCube = new String[3][3];
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
updatedCube[j][2 - i] = cubeC[i][j];
}
}
return updatedCube;
}
rotateFront 메서드 : 큐브의 앞면을 90도 회전
// rotateInnerCube 메서드 내부
cmdC.addFirst(cmdC.removeLast());
String[][] updatedCube = rotateClockwise(cubeC);
void rotateFront(String cmd) {
Deque<String> cmdFront = new ArrayDeque<>();
cmdFront.add(cubeUp[2][0] + cubeUp[2][1] + cubeUp[2][2]);
cmdFront.add(cubeRight[0][0] + cubeRight[1][0] + cubeRight[2][0]);
cmdFront.add(cubeDown[0][2] + cubeDown[0][1] + cubeDown[0][0]);
cmdFront.add(cubeLeft[2][2] + cubeLeft[1][2] + cubeLeft[0][2]);
cubeFront = rotateInnerCube(cmd, cmdFront, cubeFront);
String[] temp = saveCommandAsStringArray(cmdFront);
for (int i = 0; i < 3; i++) {
cubeUp[2][i] = Character.toString(temp[0].charAt(i));
cubeRight[i][0] = Character.toString(temp[1].charAt(i));
cubeDown[0][2 - i] = Character.toString(temp[2].charAt(i));
cubeLeft[2 - i][2] = Character.toString(temp[3].charAt(i));
}
count++;
}
printRubiksCube : 큐브의 6면을 2차원으로 펼쳐진 상태로 출력
void printRubiksCube() {
printCubeUpORDown(cubeUp);
System.out.println();
for (int i = 0; i < 3; i++) {
printCubeSide(i, cubeLeft);
printCubeSide(i, cubeFront);
printCubeSide(i, cubeRight);
printCubeSide(i, cubeBack);
System.out.println();
}
System.out.println();
printCubeUpORDown(cubeDown);
}
코테는 이렇게 하는거구나 .. 저도 언젠가 공부해볼게요;