재귀를 이용한 하노이의 탑 시각화(windows와 linux에서만 컴파일 가능)





-sleep 함수 사용에 대해..


windows에서는 windows.h헤더 내에 선언된 Sleep함수(단위 ms)를 이용.


Linux에서는,

linux의 unistd.h에 존재하는 sleep 함수는 최소 대기시간이 1초이다. 만약 1초보다 짧은 시간 동안 프로그램을 재우고 싶다면, 다른 함수가 필요하다.

usleep함수는 microsecond 단위로 대기할 수 있지만, 더이상 잘 사용되지 않는다.

time.h의 nanosleep(시간단위는 nanosecond)을 사용했다(http://stackoverflow.com/a/7684399).




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
// Visualization: Towers of Hanoi
 
#include <stdio.h>
#include <stdlib.h>
 
#ifdef _WIN32 // Windows (x64 and x86)
#include <windows.h>
#define WAIT(n) Sleep(400*(n))
#define CLRSCR() system("cls")
 
#elif defined __linux__
#include <time.h>
#define WAIT(n) nanosleep((const struct timespec[]){{0, 400000000L * (n)}}, NULL);
#define CLRSCR() system("clear && printf '\e[3J'")
#endif
 
void showTower(int arr[], int n);
void solveHanoi(int *arr, int n, int numDisks, int fromPeg, int toPeg);
void moveDisk(int *arr, int n, int fromPeg, int toPeg);
 
int main(void)
{
    int *arr;
    int size = -1;
    int fromPeg, toPeg;
    
    while (size < 0 || size > 9) {
        printf("원판의 갯수 입력(1-9): ");
        scanf("%d"&size);
    }
    getchar(); // skips '\n'
    for (;;) {
        printf("원판들이 있는 현재 막대기 입력(A, B, C): ");
        fromPeg = getchar();
        if (fromPeg == 'a' || fromPeg == 'A') {
            fromPeg = 0;
            break;
        }
        if (fromPeg == 'b' || fromPeg == 'B') {
            fromPeg = 1;
            break;
        }
        if (fromPeg == 'c' || fromPeg == 'C') {
            fromPeg = 2;
            break;
        }
    }
    getchar(); // skips '\n'
    for (;;) {
        printf("원판들이 이동할 막대기 입력 - 위에서 입력한 것과 다른 막대기(A, B, C): ");
        toPeg = getchar();
        if (fromPeg != 0 && toPeg == 'a' || toPeg == 'A') {
            toPeg = 0;
            break;
        }
        if (fromPeg != 1 && toPeg == 'b' || toPeg == 'B') {
            toPeg = 1;
            break;
        }
        if (fromPeg != 2 && toPeg == 'c' || toPeg == 'C') {
            toPeg = 2;
            break;
        }
    }
    
    /*
    원판 위치에 대한 배열 생성:
    배열의 i번째 멤버의 값은 (i+1)크기의 원판이 위치한 기둥 번호를 나타냄
    0: 기둥 A, 1: 기둥 B, 2: 기둥 C
    ex) arr[] = {0, 2, 1};
    => 크기 1의 원판은 기둥 A, 크기 2의 원판은 기둥 C, 크기 3의 원판은 기둥 B에 있음
    */
    arr = malloc(sizeof(int* size);
    
    for (int i = 0; i < size; i++) {
        arr[i] = fromPeg;
    }
 
    showTower(arr, size);
    WAIT(1);
    solveHanoi(arr, sizesize, fromPeg, toPeg);
    printf("\tdone! :)\n");
    return 0;
}
 
void showTower(int arr[], int n)
{
    int **coord;
    coord = malloc(sizeof(int ** n);
    CLRSCR();
    if (coord == NULL) {
        printf("malloc failed\n");
        exit(EXIT_FAILURE);
    }
    for (int i = 0; i < n; i++) {
        if ((coord[i] = malloc(sizeof(int* 3)) == NULL) {
            printf("malloc failed: %d\n", i);
            exit(EXIT_FAILURE);
        }
    }
 
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < 3; j++)
            coord[i][j] = 0;
    }
 
    int heightA = 0, heightB = 0, heightC = 0;
    for (int i = n - 1; i >= 0; i--)
    {
        switch (arr[i]) {
        case 0:
            coord[n - 1 - heightA++][0= i + 1;
            break;
        case 1:
            coord[n - 1 - heightB++][1= i + 1;
            break;
        case 2:
            coord[n - 1 - heightC++][2= i + 1;
            break;
        default:
            printf("error: %d\n", i);
            return;
        }
    }
 
    printf("\n\n");
    for (int i = 0; i < n; i++) {
        printf("\t");
        for (int j = 0; j < 3; j++) {
            int num = coord[i][j];
            if (!num)
                printf(":\t");
            else
                printf("%d\t", num);
 
        }
        printf("\n");
    }
    printf("\t_________________\n\tA\tB\tC\n");
 
    //frees the array
    
    for (int i = 0; i < n; i++)
        free(coord[i]);
    free(coord);    
    
    WAIT(1);    
}
 
void solveHanoi(int *arr, int n, int numDisks, int fromPeg, int toPeg)
{
    int sparePeg;
    if (numDisks == 0)
        return;
 
    switch (fromPeg + toPeg) {
    case 0 + 1:
        sparePeg = 2break;
    case 0 + 2:
        sparePeg = 1break;
    case 1 + 2:
        sparePeg = 0break;
    }
    solveHanoi(arr, n, numDisks - 1, fromPeg, sparePeg);
    moveDisk(arr, n, fromPeg, toPeg);
    solveHanoi(arr, n, numDisks - 1, sparePeg, toPeg);
}
 
void moveDisk(int *arr, int n, int fromPeg, int toPeg)
{
    for (int i = 0; i < n; i++) {
        if (arr[i] == fromPeg) {
            arr[i] = toPeg;
            break;
        }
    }
    showTower(arr, n);
}
cs


+ Recent posts