[comp.sources.games] v05i059: puzzle15 - 15 square puzzle

games@tekred.TEK.COM (09/01/88)

Submitted by: "Peter Knoppers, Delft Univ. of Technology" <uunet.uu.net!mcvax!dutesta!knop>
Comp.sources.games: Volume 5, Issue 59
Archive-name: puzzle15


#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  README Makefile puzzle15.c
# Wrapped by billr@saab on Wed Aug 31 10:35:26 1988
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(919 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
XThis is a small program that plays the 15-puzzle game
X(is that the correct name of this game ?), similar to the one
Xin the desktop of some famous personal computers.
X
XThe size of the game can be set with an optional argument,
Xdefault is 4, other sizes are 3, 5 and 6. Moves are made with
Xthe 'h', 'j', 'k' and 'l' keys (like in vi). Any other key
Xprints a diagnostic, your local interrupt key aborts the
Xgame. When all pieces are sorted the program printes the
Xnumber of moves that were used and exits.
X
XThe program is copyrighted to prevent creation and distribution of
Xa zillion different versions and/or trojan horses. If you have
Xsuggestions for improvements please mail them to me.
X
XWe compile the program by
Xcc -O puzzle15.c -lcurses -ltermilb -o puzzle15
X
XEnjoy!
X-- 
XPeter Knoppers, Delft Univ. of Technology
X.--. . - . .-.   -.- -. --- .--. .--. . .-. ... 
X...!mcvax!dutrun!dutesta!knop
X  or
Xknop@dutesta.UUCP
X
END_OF_FILE
if test 919 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(101 characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
X# simple makefile for puzzle15
Xpuzzle15: puzzle15.c
X	cc -o puzzle15 -O puzzle15.c -lcurses -ltermcap
END_OF_FILE
if test 101 -ne `wc -c <'Makefile'`; then
    echo shar: \"'Makefile'\" unpacked with wrong size!
fi
# end of 'Makefile'
fi
if test -f 'puzzle15.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'puzzle15.c'\"
else
echo shar: Extracting \"'puzzle15.c'\" \(4059 characters\)
sed "s/^X//" >'puzzle15.c' <<'END_OF_FILE'
X# include <curses.h>
X# include <signal.h>
X# define BLANK	0
X# define UP	'k'
X# define LEFT	'h'
X# define DOWN	'j'
X# define RIGHT	'l'
X
Xchar   *author = "(C) Copyright 1985, 1988 P. Knoppers";
Xchar   *release1 = "Permission to use and redistribute unmodified ";
Xchar   *release2 = "copies is granted to everyone";
X
Xchar   *malloc ();		/* to satisfy lint */
X
Xdie ()				/* nice exit on ctrl-C */
X{
X    signal (SIGINT, SIG_IGN);
X    mvprintw (23, 0, "Goodbye. ");
X    refresh ();
X    endwin ();
X    exit (0);
X}
X
Xmain (argc, argv)		/* plays a simple game "15 puzzle" */
Xchar  **argv;			/* with variations in boardsize... */
X{
X    register int    i, j;
X    int     size = 4;		/* default size of the board */
X    int     size2;
X    int    *board;
X    int     empty;		/* position of empty field */
X    int     out;
X    int     m;
X    int     swap;
X    int     nswap = 0;
X    int     movecnt = 0;
X    if (argc > 2)
X	argerr (argv[0]);
X    if (argc == 2)
X	if (sscanf (argv[1], "%d", &size) < 1)
X	    argerr (argv[0]);
X    if ((size < 3) || (size > 6))
X    {
X	fprintf (stderr, "size must be 3, 4, 5, or 6\n");
X	exit (1);
X    }
X    size2 = size * size;	/* surface area of the board */
X    board = (int *) malloc ((unsigned) size2 * sizeof (int));
X    if (board == NULL)
X    {
X	fprintf (stderr, "%s: malloc failed\n", argv[0]);
X	exit (1);
X    }
X
X    srand (getpid ());		/* initialize random number generator */
X    for (i = 1; i < size2; i++)	/* put pieces on the board */
X	board[i - 1] = i;
X    for (i = size2 - 2; i > 0; i--)/* permutate pieces */
X    {
X	j = rand () % i;
X	swap = board[i];
X	board[i] = board[j];
X	board[j] = swap;
X    }
X    for (i = 0; i < size2 - 1; i++)/* is permutation a legal position ? */
X	for (j = 0; j < i; j++)
X	    if (board[j] > board[i])
X		nswap++;
X    if (nswap % 2)
X    {				/* illegal position, swap two pieces */
X	swap = board[1];
X	board[1] = board[0];
X	board[0] = swap;
X    }
X    empty = size2 - 1;		/* empty field starts in lower right corner */
X
X    signal (SIGINT, die);
X    initscr ();
X    crmode ();
X    noecho ();
X
X    while (1)			/* until final position is reached */
X    {
X	printboard (size, board);
X	out = 1;
X	for (i = 0; i < size2 - 1; i++)
X	    if (board[i] != i + 1)
X		out = 0;
X	if (out)
X	    break;		/* game ends */
X	while (1)		/* until legal move is entered */
X	{
X	    m = getch ();
X	    if ((m != LEFT) && (m != UP) && (m != RIGHT) &&
X		    (m != DOWN))
X	    {
X		notmove ();
X		continue;	/* not a move */
X	    }
X	    if (m == LEFT)
X		if (empty % size)
X		{
X		    board[empty] = board[empty - 1];
X		    board[empty - 1] = BLANK;
X		    empty--;
X		    movecnt++;
X		    break;
X		}
X	    if (m == UP)
X		if (empty >= size)
X		{
X		    board[empty] = board[empty - size];
X		    board[empty - size] = BLANK;
X		    empty -= size;
X		    movecnt++;
X		    break;
X		}
X	    if (m == RIGHT)
X		if ((empty + 1) % size)
X		{
X		    board[empty] = board[empty + 1];
X		    board[empty + 1] = BLANK;
X		    empty++;
X		    movecnt++;
X		    break;
X		}
X	    if (m == DOWN)
X		if (empty + size < size2)
X		{
X		    board[empty] = board[empty + size];
X		    board[empty + size] = BLANK;
X		    empty += size;
X		    movecnt++;
X		    break;
X		}
X	}
X    }
X    mvprintw (22, 0, "You've reached the solution in %d moves.\n", movecnt);
X    refresh ();
X    endwin ();
X}
X
Xargerr (s)
Xchar   *s;
X{
X    fprintf (stderr, "usage: %s size\n", s);
X    exit (1);
X}
X
Xprintboard (size, board)
Xint    *board;
X{
X    register int    i, j;
X    mvprintw (0, 0, "|");	/* print top edge of board */
X    for (j = 0; j < size; j++)
X	printw ("----|");
X    for (i = 0; i < size; i++)
X    {
X	mvprintw (i * 2 + 1, 0, "| ");
X	for (j = 0; j < size; j++)
X	    if (board[size * i + j])
X		printw ("%2d | ", board[size * i + j]);
X	    else
X		printw ("   | ");
X	mvprintw (i * 2 + 2, 0, "|");
X	for (j = 0; j < size; j++)
X	    printw ("----|");
X    }
X    mvprintw (16, 0, "\n");	/* erase error messages */
X    refresh ();			/* put all this on the screen */
X}
X
Xnotmove ()
X{
X    mvprintw (16, 0,
X	    "use %c for up, %c for left, %c for right and %c for down",
X	    UP, LEFT, RIGHT, DOWN);
X    refresh ();
X}
END_OF_FILE
if test 4059 -ne `wc -c <'puzzle15.c'`; then
    echo shar: \"'puzzle15.c'\" unpacked with wrong size!
fi
# end of 'puzzle15.c'
fi
echo shar: End of shell archive.
exit 0