Annotation of researchv10no/games/hanoi.c, revision 1.1.1.1

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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.