|
|
1.1 root 1: /* cc hanoi.c -lcurses -ltermlib
2: The Tower of Hanoi problem consists of three posts
3: and a set of discs of increasing sizes. The initial
4: configuration places all the discs on one post arranged
5: with small discs on large ones. The goal is to transfer
6: all the discs to another post. There are two restrictions:
7: only one disc can be moved at any time, and it is illegal
8: to put a larger disc on a smaller.
9:
10: This implementation depends on two libraries: The curses
11: screen handling package is used to make a pretty display.
12: The getopt function is used to handle the command line options;
13: I got a public domain version from netnews.
14:
15: The options control the size of the problem and the
16: display style.
17:
18: Number of discs:
19: The default number of discs is NODISCS,
20: defined below. The -n option can change this
21: up to a maximum of MAXDISCS; the maximum is based
22: on a terminal screen with 80 columns.
23: Display Speed:
24: By default, a smooth animation algorithm is used.
25: The -f (fast) option makes hanoi less smooth,
26: displaying discs at key points in their transfers.
27: This is a pretty good choice for slow speed terminals
28: because there is still a motion illusion.
29: The -t (teleport) option shows discs only
30: after they have been moved. At high speeds,
31: this looks really cool.
32: */
33: #include <curses.h>
34: #include <ctype.h>
35: #include <signal.h>
36:
37: #define LEFT 0
38: #define MIDDLE 1
39: #define RIGHT 2
40: #define MAXDISCS 13
41: #define TOP (MAXDISCS+5)
42: #define BLANK ' '
43: #define DISC '='
44: #define NODISCS 7
45:
46: #define SMOOTH 0
47: #define FAST 1
48: #define TELEPORT 2
49:
50: int Display = SMOOTH; /* Display style: SMOOTH, FAST, or TELEPORT */
51: int Nodiscs = NODISCS; /* Number of discs, up to MAXDISCS */
52: int count[3]; /* number of discs on each post */
53: int col[3]; /* column number of each post */
54:
55: main (argc, argv)
56: char **argv;
57: {
58: initial (argc, argv);
59: hanoi (Nodiscs, LEFT, MIDDLE, RIGHT);
60: sleep (Nodiscs);
61: hanoi (Nodiscs, RIGHT, MIDDLE, LEFT);
62: finish ("Done!");
63: }
64:
65: onint ()
66: {
67: signal (SIGINT, SIG_IGN);
68: finish ("...interrupted");
69: }
70: finish (s)
71: char *s;
72: {
73: move (LINES-2, 0);
74: refresh ();
75: endwin ();
76: puts (s);
77: exit (0);
78: }
79:
80: initial (argc, argv)
81: char **argv;
82: {
83: int errflg = 0; /* any option errors? */
84: int C; /* the option flag name */
85: extern char *optarg; /* defined in getopt */
86: extern onint(); /* called if user interrupts */
87: while ((C = getopt (argc, argv, "tfn:")) != EOF)
88: {
89: switch (C)
90: {
91: case 'f': Display = FAST; break;
92: case 't': Display = TELEPORT; break;
93: case 'n': Nodiscs = atoi (optarg);
94: if (Nodiscs == 0) Nodiscs = NODISCS;
95: else if (Nodiscs > MAXDISCS) Nodiscs = MAXDISCS;
96: break;
97: default:
98: errflg++;
99: }
100: }
101: if (errflg)
102: {
103: fprintf (stderr, "USAGE: hanoi [-stf] [-n discs]\n");
104: exit (1);
105: }
106: col[LEFT] = Nodiscs;
107: col[MIDDLE] = 3*Nodiscs;
108: col[RIGHT] = 5*Nodiscs;
109: initscr ();
110: noecho ();
111: signal (SIGINT, onint);
112: display (Nodiscs);
113: }
114:
115: display (n)
116: {
117: clear ();
118: standout ();
119: mvprintw (0, 0, " The Tower of Hanoi ");
120: standend ();
121: while (n > 0)
122: mkdisc (n--, LEFT);
123: }
124:
125: /*
126: The algorithm is a simple recursive one familiar to all.
127: */
128: hanoi (n, start, inter, finish)
129: {
130: if (n > 0)
131: {
132: hanoi (n-1, start, finish, inter);
133: movedisc (n, start, finish);
134: hanoi (n-1, inter, start, finish);
135: }
136: }
137:
138: movedisc (n, start, finish)
139: {
140: rmdisc (n, start);
141: showdisc (n, start, finish);
142: mkdisc (n, finish);
143: }
144:
145: showdisc (n, start, finish)
146: {
147: int y;
148: int x;
149: int dir = (col[start] < col[finish]) ? 1 : -1;
150: if (Display == TELEPORT) return;
151: for (y = count[start]; y < Nodiscs-1; y++)
152: {
153: plotdisc (n, y, col[start], BLANK);
154: if (Display == SMOOTH) refresh ();
155: plotdisc (n, y+1, col[start], DISC);
156: if (Display == SMOOTH) refresh ();
157: }
158: refresh ();
159: for (x = col[start]; x != col[finish]; x += dir)
160: {
161: plotdisc (n, y, x, BLANK);
162: plotdisc (n, y, x+dir, DISC);
163: if (Display == SMOOTH) refresh ();
164: }
165: refresh ();
166: while (y > count[finish])
167: {
168: plotdisc (n, y--, col[finish], BLANK);
169: if (Display == SMOOTH) refresh ();
170: plotdisc (n, y, col[finish], DISC);
171: if (Display == SMOOTH) refresh ();
172: }
173: refresh ();
174: }
175:
176: mkdisc (n, pile)
177: {
178: plotdisc (n, count[pile], col[pile], DISC);
179: count[pile]++;
180: refresh ();
181: }
182:
183: rmdisc (n, pile)
184: {
185: count[pile]--;
186: plotdisc (n, count[pile], col[pile], BLANK);
187: refresh ();
188: }
189:
190: plotdisc (n, y, x, c)
191: {
192: int i;
193: move (TOP-y, x-n);
194: for (i = 1; i <= 2*n; i++)
195: addch (c);
196: }
197:
198:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.