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