home *** CD-ROM | disk | FTP | other *** search
- /* ktour.c
- *
- * Finds a knight tour of a chess board by exhaustive search.
- * Displays progress of the search graphically.
- *
- * usage: run ktour [n]
- * The option N specifies the chess board size.
- * The default and maximum value for N is 8.
- *
- * author:
- * Douglas A. Jones
- * 181-1000 Oaks Drive
- * Atlantic Highlands, NJ 07716
- *
- * This program may be freely redistributed.
- *
- * Compiled with MANX 3.6, haven't tried Lattice or earlier
- * versions of MANX.
- */
-
- #include <exec/types.h>
- #include <exec/nodes.h>
- #include <exec/tasks.h>
- #include <exec/memory.h>
- #include <intuition/intuition.h>
- #include <stdio.h>
- #include <functions.h>
-
- struct NewWindow Newwind = {
- 0,0, 0,0, /* size to be filled in later */
- -1,-1, CLOSEWINDOW,
- WINDOWCLOSE|WINDOWDEPTH|WINDOWDRAG|SMART_REFRESH,
- NULL,NULL,
- (UBYTE *)"Knight tour",
- NULL,NULL, 0,0,0,0, WBENCHSCREEN
- };
- struct Window *Wind = NULL;
- struct RastPort *Rp;
- struct GfxBase *GfxBase;
- struct IntuitionBase *IntuitionBase;
-
- /*
- * Constants for drawing chess board
- */
- #define SQSZX 31
- #define SQSZY 15
- #define X0 5
- #define Y0 11
- #define TXX0 8
- #define TXY0 10
-
- #define MXBOARDSZ 8 /* maximum board size */
- char Occupied[MXBOARDSZ][MXBOARDSZ]; /* position occupied flag */
- int Boardsz = MXBOARDSZ; /* size of chess board */
-
- /*
- * Initializes the board and then tries all starting positions
- * that are not reflections.
- * Reduces the task priority so that more important things
- * will run faster.
- */
- main(argc,argv)
- int argc;
- char **argv;
- {
- int i,j;
-
- if (argc > 1)
- Boardsz= atoi(argv[1]);
- if (Boardsz<1 || Boardsz>MXBOARDSZ)
- Boardsz= MXBOARDSZ;
- openwindow(Boardsz*SQSZX+X0+5,Boardsz*SQSZY+Y0+2);
- nice();
- for (i=0; i<Boardsz; i++) {
- for (j=0; j<Boardsz; j++) {
- Occupied[i][j]= 0;
- draw(i,j,0);
- }
- }
- for (i=0; i<(Boardsz+1)/2; i++)
- for (j=i; j<(Boardsz+1)/2; j++)
- tour(i,j,1);
- waitclose();
- }
-
- /*
- * Tries to move to position x,y.
- * If the move is legal, all subsequent moves are tried by
- * recursive call.
- * Stops and waits for the close-window gadget to be clicked
- * when a feasible solution is found.
- * Nmove is the move number.
- */
- tour(x,y,nmove)
- int x,y,nmove;
- {
-
- if (x<0 || y<0 || x>=Boardsz || y>=Boardsz)
- return; /* off the board */
- if (Occupied[x][y])
- return; /* position occupied */
- Occupied[x][y]= 1;
- draw(x,y,nmove);
- if (nmove >= Boardsz*Boardsz)
- waitclose(); /* found solution */
- chkclose(); /* give up ? */
- tour(x-1,y-2,nmove+1);
- tour(x-2,y-1,nmove+1);
- tour(x-2,y+1,nmove+1);
- tour(x-1,y+2,nmove+1);
- tour(x+1,y+2,nmove+1);
- tour(x+2,y+1,nmove+1);
- tour(x+2,y-1,nmove+1);
- tour(x+1,y-2,nmove+1);
- Occupied[x][y]= 0;
- draw(x,y,0);
- }
-
- /*
- * Opens a window in which to draw the chess board.
- * Also opens the intuition and graphics libraries.
- */
- openwindow(x,y)
- int x,y;
- {
-
- IntuitionBase= (struct IntuitionBase *)
- OpenLibrary("intuition.library",0L);
- if (IntuitionBase != NULL) {
- GfxBase= (struct GfxBase *)
- OpenLibrary("graphics.library",0L);
- if (GfxBase != NULL) {
- Newwind.Width= x;
- Newwind.Height= y;
- Wind= OpenWindow(&Newwind);
- if (Wind != NULL) {
- Rp= Wind->RPort;
- return;
- }
- fprintf(stderr,"can't open window\n");
- CloseLibrary(GfxBase);
- }
- fprintf(stderr,"can't open graphics.library\n");
- CloseLibrary(IntuitionBase);
- }
- fprintf(stderr,"can't open intuition.library\n");
- exit(1);
- }
-
- /*
- * Closes the window and libraries.
- */
- closewindow()
- {
-
- CloseWindow(Wind);
- CloseLibrary(GfxBase);
- CloseLibrary(IntuitionBase);
- }
-
- /*
- * Waits for the user to click the close-window gadget,
- * then closes the window and exits.
- */
- waitclose()
- {
-
- for (;;) {
- Wait(1L << Wind->UserPort->mp_SigBit);
- chkclose();
- }
- }
-
- /*
- * Checks to see if the close-window gadget has been clicked.
- * If so, closes the window and exits.
- */
- chkclose()
- {
- struct IntuiMessage *msg;
- long class;
- int done;
-
- done= 0;
- while (msg= (struct IntuiMessage *) GetMsg(Wind->UserPort)) {
- class= msg->Class;
- ReplyMsg(msg);
- switch (class) {
- case CLOSEWINDOW:
- done= 1;
- break;
- default:
- break;
- }
- }
- if (done) {
- closewindow();
- exit(1);
- }
- }
-
- /*
- * Draws square x,y of the chess board.
- * If n is <= 0, the background color of the square is drawn.
- * Otherwise, only the number n is drawn (presumably the
- * background was already drawn).
- */
- draw(x,y,n)
- int x,y,n;
- {
- long wx,wy,clr;
- char buf[2];
-
- wx= SQSZX*x + X0;
- wy= SQSZY*y + Y0;
- if (((x+y)&01) == 0)
- clr= 1;
- else
- clr= 0;
- if (n <= 0) { /* unoccupied */
- SetAPen(Rp,clr);
- RectFill(Rp,wx,wy,wx+SQSZX-1,wy+SQSZY-1);
- } else { /* occupied */
- SetAPen(Rp,2L);
- SetBPen(Rp,clr);
- buf[0]= n/10 + '0';
- buf[1]= n%10 + '0';
- if (buf[0] == '0')
- buf[0]= ' ';
- Move(Rp,wx+TXX0,wy+TXY0);
- Text(Rp,buf,2L);
- }
- }
-
- /*
- * Sets the task priority to -10 to let more useful tasks
- * get the processor when they want it.
- */
- nice()
- {
- struct Task *mytcb,*FindTask();
-
- mytcb= FindTask(0L);
- if (mytcb != NULL)
- SetTaskPri(mytcb,-10L);
- }
-
- #if 0 /* MANX has one of these */
- /*
- * Converts the positive decimal integer in string *s into
- * internal integer representation.
- * Doesn't check for overflow.
- */
- atoi(s)
- char *s;
- {
- int n;
-
- for (n=0; '0'<=*s && *s<='9'; s++)
- n= n*10 + *s - '0';
- return(n);
- }
- #endif
-