Annotation of researchv10no/games/hanoi.c, revision 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.