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