home *** CD-ROM | disk | FTP | other *** search
/ Fish 'n' More 2 / fishmore-publicdomainlibraryvol.ii1991xetec.iso / fish / libraries / curses_439 / examples / hanoi / hanoi.c < prev    next >
C/C++ Source or Header  |  1991-01-18  |  5KB  |  258 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 <curses.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_ORANGE,    /* Length 3 */
  43.     COLOR_MAGENTA,    /* Length 5 */
  44.     COLOR_RED,        /* Length 7 */
  45.     COLOR_BLUE,        /* Length 9 */
  46.     COLOR_GREEN,    /* Length 11 */
  47.     COLOR_GREY,        /* Length 13 */
  48.     COLOR_YELLOW,    /* Length 15 */
  49.     COLOR_CYAN,        /* Length 17 */
  50.     COLOR_WHITE,    /* 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.     cbreak();
  89.     if(LINES<24) {
  90.         fprintf(stderr, "Min screen length 24 lines\n");
  91.         endwin();
  92.         exit(1);
  93.     }
  94.     if(AutoFlag)
  95.         leaveok(stdscr, TRUE);    /* Attempt to remove cursor */
  96.     InitTiles(NTiles);
  97.     DisplayTiles();
  98.     if(AutoFlag) {
  99.         do {
  100.             AutoMove(0, 2, NTiles);
  101.         } while(!Solved(NTiles));
  102.         sleep(5);
  103.     } else {
  104.         for(;;) {
  105.             if(GetMove(&FromCol, &ToCol))
  106.                 break;
  107.             if(InvalidMove(FromCol, ToCol)) {
  108.                 mvaddstr(STATUSLINE, 0, "Invalid Move !!");
  109.                 refresh();
  110.                 beep();
  111.                 continue;
  112.             }
  113.             MakeMove(FromCol, ToCol);
  114.             if(Solved(NTiles)) {
  115.                 mvprintw(STATUSLINE, 0, "Well Done !! You did it in %d moves", NMoves);
  116.                 refresh();
  117.                 sleep(5);
  118.                 break;
  119.             }
  120.         }
  121.     }
  122.     endwin();
  123. }
  124.  
  125. InvalidMove(int From, int To)
  126. {
  127.     if(From == To)
  128.         return TRUE;
  129.     if(!Pegs[From].Count)
  130.         return TRUE;
  131.     if(Pegs[To].Count &&
  132.             Pegs[From].Length[Pegs[From].Count-1] >
  133.             Pegs[To].Length[Pegs[To].Count-1])
  134.         return TRUE;
  135.     return FALSE;
  136. }
  137.  
  138. void
  139. InitTiles(int NTiles)
  140. {
  141.     int Size, SlotNo;
  142.     
  143.     for(Size=NTiles*2+1, SlotNo=0; Size>=3; Size-=2)
  144.         Pegs[0].Length[SlotNo++] = Size;
  145.     
  146.     Pegs[0].Count = NTiles;
  147.     Pegs[1].Count = 0;
  148.     Pegs[2].Count = 0;
  149. }
  150.  
  151. void
  152. DisplayTiles()
  153. {
  154.     int Line, Peg, SlotNo;
  155.     char TileBuf[BUFSIZ];
  156.  
  157.     erase();
  158.     mvaddstr(1, 24, "T O W E R S   O F   H A N O I");
  159.     mvaddstr(3, 34, "SJR 1990");
  160.     mvprintw(19, 5, "Moves : %d", NMoves);
  161.     attron(COLOR_TAN);
  162.     standout();
  163.     mvaddstr(BASELINE, 8, "                                                               ");
  164.  
  165.     for(Line=TOPLINE; Line<BASELINE; Line++) {
  166.         mvaddch(Line, LEFTPEG, ' ');
  167.         mvaddch(Line, MIDPEG, ' ');
  168.         mvaddch(Line, RIGHTPEG, ' ');
  169.     }
  170.     mvaddch(BASELINE, LEFTPEG, '1');
  171.     mvaddch(BASELINE, MIDPEG, '2');
  172.     mvaddch(BASELINE, RIGHTPEG, '3');
  173.  
  174.     /* Draw tiles */
  175.     for(Peg=0; Peg<NPEGS; Peg++) {
  176.         for(SlotNo=0; SlotNo<Pegs[Peg].Count; SlotNo++) {
  177.             memset(TileBuf, ' ', Pegs[Peg].Length[SlotNo]);
  178.             TileBuf[Pegs[Peg].Length[SlotNo]] = '\0';
  179.             attron(TileColour[LENTOIND(Pegs[Peg].Length[SlotNo])]);
  180.             mvaddstr(BASELINE-(SlotNo+1),
  181.                     PegPos[Peg]-Pegs[Peg].Length[SlotNo]/2, TileBuf);
  182.         }
  183.     }
  184.     attrset(0);
  185.     refresh();
  186. }
  187.  
  188. GetMove(int *From, int *To)
  189. {
  190.     mvaddstr(STATUSLINE, 0, "Next move ('q' to quit) from ");
  191.     clrtoeol();
  192.     refresh();
  193.     if((*From = getch()) == 'q')
  194.         return TRUE;
  195.     *From -= ('0'+1);
  196.     addstr(" to ");
  197.     clrtoeol();
  198.     refresh();
  199.     if((*To = getch()) == 'q')
  200.         return TRUE;
  201.     *To -= ('0'+1);
  202.     move(STATUSLINE, 0);
  203.     clrtoeol();
  204.     refresh();
  205.     return FALSE;
  206. }
  207.  
  208. void
  209. MakeMove(int From, int To)
  210. {
  211.     void DisplayTiles();
  212.  
  213.     Pegs[From].Count--;
  214.     Pegs[To].Length[Pegs[To].Count] = Pegs[From].Length[Pegs[From].Count];
  215.     Pegs[To].Count++;
  216.     NMoves++;
  217.     DisplayTiles();
  218. }
  219.  
  220. void
  221. AutoMove(int From, int To, int Num)
  222. {
  223.     void MakeMove();
  224.  
  225.     if(Num == 1) {
  226.         MakeMove(From, To);
  227.         return;
  228.     }
  229.     AutoMove(From, OTHER(From, To), Num-1);
  230.     MakeMove(From, To);
  231.     AutoMove(OTHER(From, To), To, Num-1);
  232. }
  233.  
  234. Solved(int NumTiles)
  235. {
  236.     int i;
  237.  
  238.     for(i=1; i<NPEGS; i++)
  239.         if(Pegs[i].Count == NumTiles)
  240.             return TRUE;
  241.     return FALSE;
  242. }
  243.  
  244. void
  245. Usage()
  246. {
  247.     fprintf(stderr, "Usage: %s [<No Of Tiles>] [a]\n");
  248.     fprintf(stderr, "The 'a' option causes the tower to be solved automatically\n");
  249. }
  250.  
  251. #ifdef AMIGA
  252. sleep(int n)
  253. {
  254.     Delay(50*n);
  255.     return 0;
  256. }
  257. #endif /* AMIGA */
  258.