home *** CD-ROM | disk | FTP | other *** search
/ ftp.muug.mb.ca / 2014.06.ftp.muug.mb.ca.tar / ftp.muug.mb.ca / pub / src / linux / old-src / ncurses-1.8.5 / hanoi.c < prev    next >
C/C++ Source or Header  |  1993-11-27  |  5KB  |  257 lines

  1. /*
  2.  *    Name: Towers of Hanoi.
  3.  *
  4.  *    Desc:
  5.  *        This is a playable copy of towers of hanoi.
  6.  *        Its sole purpose is to demonstrate my Amiga Curses package.
  7.  *        This program should compile on any system that has Curses.
  8.  *        'hanoi'        will give a manual game with 7 playing pieces.
  9.  *        'hanoi n'    will give a manual game with n playing pieces.
  10.  *        'hanoi n a' will give an auto solved game with n playing pieces.
  11.  *
  12.  *    Author: Simon J Raybould    (sie@fulcrum.bt.co.uk).
  13.  *
  14.  *    Date: 05.Nov.90
  15.  *
  16.  */
  17.  
  18. #include <ncurses.h>
  19.  
  20. #define NPEGS            3    /* This is not configurable !! */
  21. #define MINTILES        3
  22. #define MAXTILES        9
  23. #define DEFAULTTILES    7
  24. #define TOPLINE            6
  25. #define BASELINE        16
  26. #define STATUSLINE        (LINES-3)
  27. #define LEFTPEG            19
  28. #define MIDPEG            39
  29. #define RIGHTPEG        59
  30.  
  31. #define LENTOIND(x)        (((x)-1)/2-1)
  32. #define OTHER(a,b)        (3-((a)+(b)))
  33.  
  34. struct Peg {
  35.     int Length[MAXTILES];
  36.     int Count;
  37. };
  38.  
  39. struct Peg Pegs[NPEGS];
  40. int PegPos[] = { LEFTPEG, MIDPEG, RIGHTPEG };
  41. int TileColour[] = {
  42.     COLOR_GREEN,    /* Length 3 */
  43.     COLOR_MAGENTA,    /* Length 5 */
  44.     COLOR_RED,    /* Length 7 */
  45.     COLOR_BLUE,    /* Length 9 */
  46.     COLOR_CYAN,    /* Length 11 */
  47.     COLOR_YELLOW,     /* Length 13 */
  48.     COLOR_GREEN,      /* Length 15 */
  49.     COLOR_MAGENTA,    /* Length 17 */
  50.     COLOR_RED,    /* Length 19 */
  51. };
  52. int NMoves = 0;
  53.  
  54. main(int argc, char **argv)
  55. {
  56.     int NTiles, FromCol, ToCol, catch();
  57.     unsigned char AutoFlag = 0;
  58.     void InitTiles(), DisplayTiles(), MakeMove(), AutoMove(), Usage();
  59.  
  60.     switch(argc) {
  61.     case 1:
  62.         NTiles = DEFAULTTILES;
  63.         break;
  64.     case 2:
  65.         NTiles = atoi(argv[1]);
  66.         if(NTiles>MAXTILES || NTiles<MINTILES) {
  67.             fprintf(stderr, "Range %d to %d\n", MINTILES, MAXTILES);
  68.             exit(1);
  69.         }
  70.         break;
  71.     case 3:
  72.         if(strcmp(argv[2], "a")) {
  73.             Usage();
  74.             exit(1);
  75.         }
  76.         NTiles = atoi(argv[1]);
  77.         if(NTiles>MAXTILES || NTiles<MINTILES) {
  78.             fprintf(stderr, "Range %d to %d\n", MINTILES, MAXTILES);
  79.             exit(1);
  80.         }
  81.         AutoFlag = TRUE;
  82.         break;
  83.     default:
  84.         Usage();
  85.         exit(1);
  86.     }
  87.     initscr();
  88.     start_color();
  89.     {
  90.     int i;
  91.     for (i = 0; i < 9; i++)
  92.         init_pair(i, TileColour[i], COLOR_BLACK);
  93.     }
  94.     cbreak();
  95.     if(LINES<24) {
  96.         fprintf(stderr, "Min screen length 24 lines\n");
  97.         endwin();
  98.         exit(1);
  99.     }
  100.     if(AutoFlag)
  101.         leaveok(stdscr, TRUE);    /* Attempt to remove cursor */
  102.     InitTiles(NTiles);
  103.     DisplayTiles();
  104.     if(AutoFlag) {
  105.         do {
  106.             AutoMove(0, 2, NTiles);
  107.         } while(!Solved(NTiles));
  108.         sleep(5);
  109.     } else {
  110.         for(;;) {
  111.             if(GetMove(&FromCol, &ToCol))
  112.                 break;
  113.             if(InvalidMove(FromCol, ToCol)) {
  114.                 mvaddstr(STATUSLINE, 0, "Invalid Move !!");
  115.                 refresh();
  116.                 beep();
  117.                 continue;
  118.             }
  119.             MakeMove(FromCol, ToCol);
  120.             if(Solved(NTiles)) {
  121.                 mvprintw(STATUSLINE, 0, "Well Done !! You did it in %d moves", NMoves);
  122.                 refresh();
  123.                 sleep(5);
  124.                 break;
  125.             }
  126.         }
  127.     }
  128.     endwin();
  129. }
  130.  
  131. InvalidMove(int From, int To)
  132. {
  133.     if(From == To)
  134.         return TRUE;
  135.     if(!Pegs[From].Count)
  136.         return TRUE;
  137.     if(Pegs[To].Count &&
  138.             Pegs[From].Length[Pegs[From].Count-1] >
  139.             Pegs[To].Length[Pegs[To].Count-1])
  140.         return TRUE;
  141.     return FALSE;
  142. }
  143.  
  144. void
  145. InitTiles(int NTiles)
  146. {
  147.     int Size, SlotNo;
  148.     
  149.     for(Size=NTiles*2+1, SlotNo=0; Size>=3; Size-=2)
  150.         Pegs[0].Length[SlotNo++] = Size;
  151.     
  152.     Pegs[0].Count = NTiles;
  153.     Pegs[1].Count = 0;
  154.     Pegs[2].Count = 0;
  155. }
  156.  
  157. void
  158. DisplayTiles()
  159. {
  160.     int Line, Peg, SlotNo;
  161.     char TileBuf[BUFSIZ];
  162.  
  163.     clear();
  164.     mvaddstr(1, 24, "T O W E R S   O F   H A N O I");
  165.     mvaddstr(3, 34, "SJR 1990");
  166.     mvprintw(19, 5, "Moves : %d", NMoves);
  167.     standout();
  168.     mvaddstr(BASELINE, 8, "                                                               ");
  169.  
  170.     for(Line=TOPLINE; Line<BASELINE; Line++) {
  171.         mvaddch(Line, LEFTPEG, ' ');
  172.         mvaddch(Line, MIDPEG, ' ');
  173.         mvaddch(Line, RIGHTPEG, ' ');
  174.     }
  175.     mvaddch(BASELINE, LEFTPEG, '1');
  176.     mvaddch(BASELINE, MIDPEG, '2');
  177.     mvaddch(BASELINE, RIGHTPEG, '3');
  178.     standend();
  179.  
  180.     /* Draw tiles */
  181.     for(Peg=0; Peg<NPEGS; Peg++) {
  182.         for(SlotNo=0; SlotNo<Pegs[Peg].Count; SlotNo++) {
  183.             memset(TileBuf, ' ', Pegs[Peg].Length[SlotNo]);
  184.             TileBuf[Pegs[Peg].Length[SlotNo]] = '\0';
  185.             attrset(COLOR_PAIR(LENTOIND(Pegs[Peg].Length[SlotNo])));
  186.             mvaddstr(BASELINE-(SlotNo+1),
  187.                     PegPos[Peg]-Pegs[Peg].Length[SlotNo]/2, TileBuf);
  188.         }
  189.     }
  190.     attrset(A_NORMAL);
  191.     refresh();
  192. }
  193.  
  194. GetMove(int *From, int *To)
  195. {
  196.     mvaddstr(STATUSLINE, 0, "Next move ('q' to quit) from ");
  197.     clrtoeol();
  198.     refresh();
  199.     if((*From = getch()) == 'q')
  200.         return TRUE;
  201.     *From -= ('0'+1);
  202.     addstr(" to ");
  203.     clrtoeol();
  204.     refresh();
  205.     if((*To = getch()) == 'q')
  206.         return TRUE;
  207.     *To -= ('0'+1);
  208.     move(STATUSLINE, 0);
  209.     clrtoeol();
  210.     refresh();
  211.     return FALSE;
  212. }
  213.  
  214. void
  215. MakeMove(int From, int To)
  216. {
  217.     void DisplayTiles();
  218.  
  219.     Pegs[From].Count--;
  220.     Pegs[To].Length[Pegs[To].Count] = Pegs[From].Length[Pegs[From].Count];
  221.     Pegs[To].Count++;
  222.     NMoves++;
  223.     DisplayTiles();
  224. }
  225.  
  226. void
  227. AutoMove(int From, int To, int Num)
  228. {
  229.     void MakeMove();
  230.  
  231.     if(Num == 1) {
  232.         MakeMove(From, To);
  233.         return;
  234.     }
  235.     AutoMove(From, OTHER(From, To), Num-1);
  236.     MakeMove(From, To);
  237.     AutoMove(OTHER(From, To), To, Num-1);
  238. }
  239.  
  240. Solved(int NumTiles)
  241. {
  242.     int i;
  243.  
  244.     for(i=1; i<NPEGS; i++)
  245.         if(Pegs[i].Count == NumTiles)
  246.             return TRUE;
  247.     return FALSE;
  248. }
  249.  
  250. void
  251. Usage()
  252. {
  253.     fprintf(stderr, "Usage: %s [<No Of Tiles>] [a]\n");
  254.     fprintf(stderr, "The 'a' option causes the tower to be solved automatically\n");
  255. }
  256.  
  257.