프로그래밍/C++언어
2016. 4. 15. 03:59
하노이탑은 여러 프로그래머들이 재귀함수를 공부할때 주로 찾는 구조이다. 하지만 하노이탑을 게임으로 만들면 재귀는 버리고 구조체 배열을 빠삭하게 알아야한다.
기본적으로 룰은 이렇다.
1) 0인 원반은 움직일 수 없다.
2) 같은 자리로 이동은 불가능하다 ex)1번 원반을 고르고 1번에 착지
3) 하노이탑의 규칙에 위배되서는 안된다.
- 한 번에 하나의 원판만 옮길 수 있다.
- 큰 원판이 작은 원판 위에 있어서는 안 된다.
4) 다시하기를 할 경우 초기화된다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 | #include<iostream> typedef struct hanoitower { int hanoi[3][3]; }hanoitower; void show(hanoitower &hanoi) { for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) std::cout << hanoi.hanoi[i][j] << " "; std::cout << "\n"; } std::cout << "A B C" << std::endl; } void select(hanoitower &hanoi) { std::cout << "이동할 원반을 고르세요.(단 0인 원반은 움직일 수 없습니다.)\n"; if (hanoi.hanoi[0][0] == 1 || hanoi.hanoi[0][0] == 2 || hanoi.hanoi[0][0] == 3) std::cout << "1.A원반 : " << hanoi.hanoi[0][0]; else if (hanoi.hanoi[1][0] == 1 || hanoi.hanoi[1][0] == 2 || hanoi.hanoi[1][0] == 3) std::cout << "1.A원반 : " << hanoi.hanoi[1][0]; else std::cout << "1.A원반 : " << hanoi.hanoi[2][0]; if (hanoi.hanoi[0][1] == 1 || hanoi.hanoi[0][1] == 2 || hanoi.hanoi[0][1] == 3) std::cout << "\t2.B원반 : " << hanoi.hanoi[0][1]; else if (hanoi.hanoi[1][1] == 1 || hanoi.hanoi[1][1] == 2 || hanoi.hanoi[1][1] == 3) std::cout << "\t2.B원반 : " << hanoi.hanoi[1][1]; else std::cout << "\t2.B원반 : " << hanoi.hanoi[2][1]; if (hanoi.hanoi[0][2] == 1 || hanoi.hanoi[0][2] == 2 || hanoi.hanoi[0][2] == 3) std::cout << "\t3.C원반 : " << hanoi.hanoi[0][2] << std::endl; else if (hanoi.hanoi[1][2] == 1 || hanoi.hanoi[1][2] == 2 || hanoi.hanoi[1][2] == 3) std::cout << "\t3.C원반 : " << hanoi.hanoi[1][2] << std::endl; else std::cout << "\t3.C원반 : " << hanoi.hanoi[2][2] << std::endl; } void when() { std::cout << "어디로 옮길건가요?(단 하노이탑 규칙에 어긋나는 이동은 할 수 없습니다.)" << std::endl; std::cout << "1:A,\t2:B,\t3:C" << std::endl; } bool check1(hanoitower &hanoi, int input2) // 0인지 아닌지 체크하는 함수 { if (input2 == 1) if (hanoi.hanoi[0][0] == 0 && hanoi.hanoi[1][0] == 0 && hanoi.hanoi[2][0] == 0) { std::cout << "0인 원반은 이동이 불가능합니다.\n"; return false; } if (input2 == 2) if (hanoi.hanoi[0][1] == 0 && hanoi.hanoi[1][1] == 0 && hanoi.hanoi[2][1] == 0) { std::cout << "0인 원반은 이동이 불가능합니다.\n"; return false; } if (input2 == 3) if (hanoi.hanoi[0][2] == 0 && hanoi.hanoi[1][2] == 0 && hanoi.hanoi[2][2] == 0) { std::cout << "0인 원반은 이동이 불가능합니다.\n"; return false; } return true; } bool check2(hanoitower &hanoi, int input2, int input3, int before, int after) //하노이탑 기본 규칙 체크 { if (hanoi.hanoi[0][input2 - 1] != 0) { before = hanoi.hanoi[0][input2 - 1]; } else if (hanoi.hanoi[1][input2 - 1] != 0) { before = hanoi.hanoi[1][input2 - 1]; } else { before = hanoi.hanoi[2][input2 - 1]; } if (hanoi.hanoi[0][input3 - 1] != 0) { after = hanoi.hanoi[0][input3 - 1]; } else if (hanoi.hanoi[1][input3 - 1] != 0) { after = hanoi.hanoi[1][input3 - 1]; } else { after = hanoi.hanoi[2][input3 - 1]; } if (after == 0) return true; if (before > after) { std::cout << "하노이탑 규칙에 위배됩니다.\n"; return false; } else if (before == after) { std::cout << "같은 곳으로 움직일 수는 없습니다.\n"; return false; } else return true; } void move(hanoitower &hanoi, int input2, int input3, int before) // 이동 { if (hanoi.hanoi[0][input2 - 1] != 0) { before = hanoi.hanoi[0][input2 - 1]; hanoi.hanoi[0][input2 - 1] = 0; } else if (hanoi.hanoi[1][input2 - 1] != 0) { before = hanoi.hanoi[1][input2 - 1]; hanoi.hanoi[1][input2 - 1] = 0; } else { before = hanoi.hanoi[2][input2 - 1]; hanoi.hanoi[2][input2 - 1] = 0; } if (hanoi.hanoi[2][input3 - 1] == 0) { hanoi.hanoi[2][input3 - 1] = before; } else if (hanoi.hanoi[1][input3 - 1] == 0) { hanoi.hanoi[1][input3 - 1] = before; } else { hanoi.hanoi[0][input3 - 1] = before; } } void main() { while (1) { hanoitower hanoi; for (int i = 0; i < 3; i++) for (int j = 0; j < 3; j++) hanoi.hanoi[i][j] = 0; hanoi.hanoi[0][0] = 1; hanoi.hanoi[1][0] = 2; hanoi.hanoi[2][0] = 3; int input; // 원반이동 및 다시하기 받는 변수 int input2; // 이동할 원반을 받는 변수 int input3; // 이동할 위치를 받는 변수 int before = 0; int after = 0; bool check = true; show(hanoi); while (1) { std::cout << "1. 원반이동 2. 다시하기 "; std::cin >> input; if (input == 1) { do { select(hanoi); std::cin >> input2; check = check1(hanoi, input2); } while (!check); do { when(); std::cin >> input3; check = check2(hanoi, input2, input3, before, after); } while (!check); move(hanoi, input2, input3, before); show(hanoi); if (hanoi.hanoi[0][2] == 1 && hanoi.hanoi[1][2] == 2 && hanoi.hanoi[2][2] == 3) { printf("당신이 이겼습니다."); return; } } else if (input == 2) break; } } } | cs |
필자가 이 코드를 새벽에 짜느라 너무 하드코딩해버리는 감이 있지 않나 싶다. 수정할 요지는 많으니 공부할때 충분히 반복문을 추가시켜서 코드를 간결하게 하는것도 좋을 것 같다.
'프로그래밍 > C++언어' 카테고리의 다른 글
콘솔게임(오목)만들기. (5) | 2016.06.07 |
---|---|
[C++언어]더미노드가 있는 단순연결리스트로 주소록 만들기 (0) | 2016.04.15 |
posted by 천마서생