-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhanoi_2.c
171 lines (139 loc) · 3.88 KB
/
hanoi_2.c
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
#include <stdio.h>
#include <stdlib.h>
/* 塔の高さ */
#define HEIGHT 6
/* 塔の本数(3固定) */
#define NUM 3
/* 塔に名前をつける */
typedef enum {
src = 0,
dst,
work
} type;
void move(int **, type, type);
int pop(int **, type);
void push(int **, type, int);
void print_hanoi(int **);
void print_hanoi_debug(int **);
void hanoi_func(int **, int, type, type, type);
/* 高さ height のハノイの塔を解く関数 */
void hanoi_func(int **tower, int height, type src, type dst, type work){
if(height > 1){
/* dst と work を置き換えて高さ height - 1のハノイの塔を解く */
hanoi_func(tower, height - 1, src, work, dst);
}
/* 一番大きい円盤を空いている dst へ移動 */
/* height が 1 の場合はこの処理のみを行う */
move(tower, src, dst);
if(height > 1){
/* src と work を置き換えて高さ height - 1のハノイの塔を解く */
hanoi_func(tower, height - 1, work, dst, src);
}
}
/* 塔の状態を表示する関数 */
void print_hanoi(int **tower){
int i, j, k;
int max_space;
int pre_space;
int num_print;
max_space = 2 * (HEIGHT + 1);
for(j = 0; j < HEIGHT; j++){
for(i = 0; i < NUM; i++){
/* 空の場合はスペースのみを出力 */
if(tower[i][j] == -1){
for(k = 0; k < max_space; k++){
printf(" ");
}
} else {
/* 空でない場合は円盤の大きさ * 2 の数の # を出力 */
num_print = 2 * tower[i][j];
pre_space = (max_space - num_print) / 2;
for(k = 0; k < pre_space; k++){
printf(" ");
}
for(k = pre_space; k < pre_space + num_print; k++){
printf("#");
}
for(k = pre_space + num_print; k < max_space; k++){
printf(" ");
}
}
}
printf("\n");
}
}
/* 塔の状態を表示する関数 */
void print_hanoi_debug(int **tower){
char c;
/* 塔の状態を表示 */
print_hanoi(tower);
/* プログラムをとめるための scanf */
printf("Press Enter Key...");
scanf("%c", &c);
}
/* s で指定された塔から d で指定された塔に円盤を移動する関数 */
void move(int **tower, type s, type d){
int data;
static int count = 1;
/* デバッグ用の表示 */
printf("move %d : %d -> %d\n", count, s, d);
/* s の塔から円盤の大きさを取得し d の塔に移動 */
data = pop(tower, s);
push(tower, d, data);
/* デバッグ用の表示 */
print_hanoi_debug(tower);
count++;
}
/* 指定された塔に指定された値を格納する関数 */
void push(int **tower, type s, int data){
int i;
/* 塔の一番下から空いている箇所を探す */
for(i = HEIGHT - 1; i >= 0; i--){
if(tower[s][i] == -1){
break;
}
}
tower[s][i] = data;
}
/* 指定された塔の一番上の円盤を取得する関数 */
int pop(int **tower, type s){
int i;
int ret;
/* 円盤のある箇所を塔の一番上から探す */
for(i = 0; i < HEIGHT; i++){
if(tower[s][i] != -1){
break;
}
}
/* 塔の一番上のデータを取得 */
ret = tower[s][i];
/* 取得された箇所は空に */
tower[s][i] = -1
;
return ret;
}
int main(void){
int **tower;
int i;
/* 塔の状態を格納するデータのためのメモリ取得 */
tower = (int**)malloc(sizeof(int*) * NUM);
for(i = 0; i < NUM; i++){
tower[i] = (int*)malloc(sizeof(int) * HEIGHT);
}
/* ハノイの塔の初期状態を設定 */
for(i = 0; i < HEIGHT; i++){
/* src には塔の上から順に小さい円盤を積む */
tower[src][i] = i + 1;
/* dst と work は全て空 */
tower[dst][i] = -1;
tower[work][i] = -1;
}
/* 高さHEIGHTのハノイの塔を解く */
hanoi_func(tower, HEIGHT, src, dst, work);
/* 塔の状態を格納するデータを解放 */
for(i = 0; i < NUM; i++){
free(tower[i]);
}
free(tower);
return 0;
}