|
|
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.