home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / games / volume5 / puzzle15 / puzzle15.c < prev    next >
Text File  |  1988-08-31  |  4KB  |  180 lines

  1. # include <curses.h>
  2. # include <signal.h>
  3. # define BLANK    0
  4. # define UP    'k'
  5. # define LEFT    'h'
  6. # define DOWN    'j'
  7. # define RIGHT    'l'
  8.  
  9. char   *author = "(C) Copyright 1985, 1988 P. Knoppers";
  10. char   *release1 = "Permission to use and redistribute unmodified ";
  11. char   *release2 = "copies is granted to everyone";
  12.  
  13. char   *malloc ();        /* to satisfy lint */
  14.  
  15. die ()                /* nice exit on ctrl-C */
  16. {
  17.     signal (SIGINT, SIG_IGN);
  18.     mvprintw (23, 0, "Goodbye. ");
  19.     refresh ();
  20.     endwin ();
  21.     exit (0);
  22. }
  23.  
  24. main (argc, argv)        /* plays a simple game "15 puzzle" */
  25. char  **argv;            /* with variations in boardsize... */
  26. {
  27.     register int    i, j;
  28.     int     size = 4;        /* default size of the board */
  29.     int     size2;
  30.     int    *board;
  31.     int     empty;        /* position of empty field */
  32.     int     out;
  33.     int     m;
  34.     int     swap;
  35.     int     nswap = 0;
  36.     int     movecnt = 0;
  37.     if (argc > 2)
  38.     argerr (argv[0]);
  39.     if (argc == 2)
  40.     if (sscanf (argv[1], "%d", &size) < 1)
  41.         argerr (argv[0]);
  42.     if ((size < 3) || (size > 6))
  43.     {
  44.     fprintf (stderr, "size must be 3, 4, 5, or 6\n");
  45.     exit (1);
  46.     }
  47.     size2 = size * size;    /* surface area of the board */
  48.     board = (int *) malloc ((unsigned) size2 * sizeof (int));
  49.     if (board == NULL)
  50.     {
  51.     fprintf (stderr, "%s: malloc failed\n", argv[0]);
  52.     exit (1);
  53.     }
  54.  
  55.     srand (getpid ());        /* initialize random number generator */
  56.     for (i = 1; i < size2; i++)    /* put pieces on the board */
  57.     board[i - 1] = i;
  58.     for (i = size2 - 2; i > 0; i--)/* permutate pieces */
  59.     {
  60.     j = rand () % i;
  61.     swap = board[i];
  62.     board[i] = board[j];
  63.     board[j] = swap;
  64.     }
  65.     for (i = 0; i < size2 - 1; i++)/* is permutation a legal position ? */
  66.     for (j = 0; j < i; j++)
  67.         if (board[j] > board[i])
  68.         nswap++;
  69.     if (nswap % 2)
  70.     {                /* illegal position, swap two pieces */
  71.     swap = board[1];
  72.     board[1] = board[0];
  73.     board[0] = swap;
  74.     }
  75.     empty = size2 - 1;        /* empty field starts in lower right corner */
  76.  
  77.     signal (SIGINT, die);
  78.     initscr ();
  79.     crmode ();
  80.     noecho ();
  81.  
  82.     while (1)            /* until final position is reached */
  83.     {
  84.     printboard (size, board);
  85.     out = 1;
  86.     for (i = 0; i < size2 - 1; i++)
  87.         if (board[i] != i + 1)
  88.         out = 0;
  89.     if (out)
  90.         break;        /* game ends */
  91.     while (1)        /* until legal move is entered */
  92.     {
  93.         m = getch ();
  94.         if ((m != LEFT) && (m != UP) && (m != RIGHT) &&
  95.             (m != DOWN))
  96.         {
  97.         notmove ();
  98.         continue;    /* not a move */
  99.         }
  100.         if (m == LEFT)
  101.         if (empty % size)
  102.         {
  103.             board[empty] = board[empty - 1];
  104.             board[empty - 1] = BLANK;
  105.             empty--;
  106.             movecnt++;
  107.             break;
  108.         }
  109.         if (m == UP)
  110.         if (empty >= size)
  111.         {
  112.             board[empty] = board[empty - size];
  113.             board[empty - size] = BLANK;
  114.             empty -= size;
  115.             movecnt++;
  116.             break;
  117.         }
  118.         if (m == RIGHT)
  119.         if ((empty + 1) % size)
  120.         {
  121.             board[empty] = board[empty + 1];
  122.             board[empty + 1] = BLANK;
  123.             empty++;
  124.             movecnt++;
  125.             break;
  126.         }
  127.         if (m == DOWN)
  128.         if (empty + size < size2)
  129.         {
  130.             board[empty] = board[empty + size];
  131.             board[empty + size] = BLANK;
  132.             empty += size;
  133.             movecnt++;
  134.             break;
  135.         }
  136.     }
  137.     }
  138.     mvprintw (22, 0, "You've reached the solution in %d moves.\n", movecnt);
  139.     refresh ();
  140.     endwin ();
  141. }
  142.  
  143. argerr (s)
  144. char   *s;
  145. {
  146.     fprintf (stderr, "usage: %s size\n", s);
  147.     exit (1);
  148. }
  149.  
  150. printboard (size, board)
  151. int    *board;
  152. {
  153.     register int    i, j;
  154.     mvprintw (0, 0, "|");    /* print top edge of board */
  155.     for (j = 0; j < size; j++)
  156.     printw ("----|");
  157.     for (i = 0; i < size; i++)
  158.     {
  159.     mvprintw (i * 2 + 1, 0, "| ");
  160.     for (j = 0; j < size; j++)
  161.         if (board[size * i + j])
  162.         printw ("%2d | ", board[size * i + j]);
  163.         else
  164.         printw ("   | ");
  165.     mvprintw (i * 2 + 2, 0, "|");
  166.     for (j = 0; j < size; j++)
  167.         printw ("----|");
  168.     }
  169.     mvprintw (16, 0, "\n");    /* erase error messages */
  170.     refresh ();            /* put all this on the screen */
  171. }
  172.  
  173. notmove ()
  174. {
  175.     mvprintw (16, 0,
  176.         "use %c for up, %c for left, %c for right and %c for down",
  177.         UP, LEFT, RIGHT, DOWN);
  178.     refresh ();
  179. }
  180.