⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 landmine.c

📁 开放源码实时操作系统源码.
💻 C
📖 第 1 页 / 共 3 页
字号:
	printline(6, "1-leg games:%3d\n", games1[index]);
	printline(7, "Lost games: %3d\n", games0[index]);

	if (games) {
		printline(9, "Legs/game: %3d.%03d\n", score / games,
			((score * 1000) / games) % 1000);

		printline(10, "Steps/game:%3d.%03d\n", allsteps / games,
			((allsteps * 1000) / games) % 1000);
	}
}


/*
 * Printf routine for windows, which can print at particular lines.
 * A negative line number means continue printing at the previous location.
 * Assumes the status window for output.
 */
static void printline(GR_COORD row, char * fmt, ...)
{
	va_list		ap;
	GR_COUNT	cc;
	GR_SIZE		width;
	char		*cp;
	char		buf[256];

	va_start(ap, fmt);
	vsprintf(buf, fmt, ap);
	va_end(ap);

	if (row >= 0) {
		charxpos = 0;
		charypos = charheight * row + charheight - 1;
	}

	cp = buf;
	for (;;) {
		cc = 0;
		width = 0;
		while (*cp >= ' ') {
			width += fi.widths[(int)*cp++];
			cc++;
		}
		if (width) {
			GrText(statwid, statgc, charxpos, charypos,
				cp - cc, cc, GR_TFBOTTOM);
			charxpos += width;
		}

		switch (*cp++) {
			case '\0':
				return;
			case '\n':
				newline();
				break;
			case '\r':
				charxpos = 0;
				break;
		}
	}
}


/*
 * Clear the remainder of the line and move to the next line.
 * This assumes output is in the status window.
 */
static void
newline()
{
	GrFillRect(statwid, blackgc, charxpos, charypos - charheight + 1,
		statwidth - charxpos, charheight);
	charxpos = 0;
	charypos += charheight;
}


/*
 * Translate a board window coordinate into a cell position.
 * If the coordinate is outside of the window, or exactly on one
 * of the interior lines, then a coordinate of 0 is returned.
 */
static POS
findcell(x, y)
	GR_COORD	x;
	GR_COORD	y;
{
	GR_COORD	row;
	GR_COORD	col;

	if (((x % xp) == 0) || ((y % yp) == 0))
		return 0;
	row = (y / yp) + 1;
	col = (x / xp) + 1;
	if ((row <= 0) || (row > size) || (col <= 0) || (col > size))
		return 0;
	return boardpos(row, col);
}


/*
 * Initialize the board for playing
 */
static void
newgame()
{
	GR_COORD	row;
	GR_COORD	col;
	GR_COUNT	count;
	CELL		cell;
	POS		pos;

	for (row = 0; row < FULLSIZE; row++) {
		for (col = 0; col < FULLSIZE; col++) {
			cell = F_EMPTY;
			if (badsquare(row) || badsquare(col))
				cell |= F_EDGE;
			board[boardpos(row, col)] = cell;
		}
	}

	playing = GR_TRUE;
	count = 0;
	legs = 2;
	steps = 0;
	drawstatus();
	setcursor();

	while (count < mines) {
		do {
			row = (rand() / 16) % (size * size + 1);
		} while (row == (size * size));

		col = (row % size) + 1;
		row = (row / size) + 1;
		pos = boardpos(row, col);

		if ((pos == boardpos(1,1)) || (pos == boardpos(1,2)) ||
			(pos == boardpos(2,1)) || (pos == boardpos(2,2)) ||
			(pos == boardpos(size,size)))
				continue;

		if (!ismine(board[pos]) && checkpath(pos))
			count++;
	}

	board[boardpos(1,1)] = (F_OLD | '0');

	GrClearWindow(boardwid, GR_TRUE);
}


/*
 * Check to see if there is still a path from the top left corner to the
 * bottom right corner, if a new mine is placed at the indicated position.
 * Returns GR_TRUE if mine was successfully placed.
 */
static GR_BOOL
checkpath(pos)
	POS		pos;		/* position to place mine at */
{
	CELL		*bp;		/* current board position */
	CELL		*endbp;		/* ending position */
	POS		endpos;		/* ending position */
	GR_COUNT	count;		/* number of neighbors */
	GR_COUNT	i;		/* loop counter */
	GR_BOOL		more;		/* GR_TRUE if new square reached */

	/*
	 * Begin by assuming there is a mine at the specified location,
	 * and then count neighbors.  If there are less than two other
	 * mines or edge squares, then there must still be a path.
	 */
	board[pos] |= F_MINE;

	count = 0;

	for (i = 7; i >= 0; i--) {
		if (board[pos + steptable[i]] & (F_MINE | F_EDGE))
		count++;
	}

	if (count < 2)
		return GR_TRUE;

	/*
	 * Two or more neighbors, so we must do the full check.
	 * First clear the reach flag, except for the top left corner.
	 */
	endpos = boardpos(size, size);
	bp = &board[endpos];
	endbp = bp;
	while (bp != board)
		*bp-- &= ~F_REACH;
	board[boardpos(1,1)] |= F_REACH;

	/*
	 * Now loop looking for new squares next to already reached squares.
	 * Stop when no more changes are found, or when the lower right
	 * corner is reached.
	 */
	do {
		more = GR_FALSE;
		for (bp = &board[boardpos(1,1)]; bp != endbp; bp++) {
			if (*bp & F_REACH) {
				for (i = 7; i >= 0; i--) {
					if ((bp[steptable[i]] & (F_MINE | F_REACH | F_EDGE)) == 0) {
						bp[steptable[i]] |= F_REACH;
						more = GR_TRUE;
					}
				}
			}
		}

		if (board[endpos] & F_REACH)
			return GR_TRUE;
	} while (more);

	/*
	 * Cannot reach the lower right corner, so remove the mine and fail.
	 */
	board[pos] &= ~F_MINE;

	return GR_FALSE;
}


/*
 * Move to a particular position and see if we hit a mine.
 * If not, then count the number of mines adjacent to us so it can be seen.
 * If we are stepping onto a location where we remembered a mine is at,
 * then don't do it.  Moving is only allowed to old locations, or to
 * locations adjacent to old ones.
 */
static void
movetopos(newpos)
	POS		newpos;		/* position to move to */
{
	POS		fixpos;		/* position to fix up */
	CELL		cell;		/* current cell */
	GR_COUNT	count;		/* count of cells */
	GR_COUNT	i;		/* index for neighbors */

	if ((newpos < 0) || (newpos >= (FULLSIZE * FULLSIZE)) || !playing)
		return;

	cell = board[newpos];

	if (isedge(cell) || (isseen(cell)) || isold(cell))
		return;

	count = isold(cell);
	for (i = 0; i < 8; i++)
		if (isold(board[newpos + steptable[i]]))
			count++;

	if (count <= 0)
		return;

	cell = (cell & F_FLAGS) | F_OLD;
	steps++;

	PRINTSTEPS;

	if (ismine(cell)) {		/* we hit a mine */
		legs--;
		board[newpos] = (F_REMEMBER | F_MINE);
		cell = (F_EMPTY | F_OLD);
		board[newpos] = cell;
		drawbomb(newpos, redgc, GR_TRUE);
		clearcell(newpos);
		setcursor();
		for (i = 0; i < 8; i++) {
			fixpos = newpos + steptable[i];
			if (isold(board[fixpos])) {
				board[fixpos]--;
				drawcell(fixpos);
			}
		}
		drawstatus();
	}

	count = 0;
	for (i = 0; i < 8; i++)
		if (ismine(board[newpos + steptable[i]]))
			count++;
	board[newpos] = cell | (count + '0');

	drawcell(newpos);

	if ((legs <= 0) || (newpos == boardpos(size,size)))
		gameover();
}


/*
 * Remember or forget the location of a mine.
 * This is for informational purposes only and does not affect anything.
 */
static void
togglecell(pos)
	POS	pos;		/* position to toggle */
{
	CELL	cell;

	if ((pos <= 0) || !playing)
		return;

	cell = board[pos];
	if (isknown(cell)) {
		if (!isseen(cell))
			return;
		board[pos] = (board[pos] & F_FLAGS) | F_EMPTY;
		clearcell(pos);
		return;
	}

	board[pos] = (board[pos] & F_FLAGS) | F_REMEMBER;
	drawcell(pos);
}


/*
 * Here when the game is over.
 * Show where the mines are, and give the results.
 */
static void
gameover()
{
	POS	pos;
	CELL	cell;

	playing = GR_FALSE;
	switch (legs) {
		case 0:
			games0[index]++;
			steps0[index] += steps;
			break;
		case 1:
			games1[index]++;
			steps1[index] += steps;
			break;
		case 2:
			games2[index]++;
			steps2[index] += steps;
			break;
	}

	for (pos = 0; pos < (FULLSIZE * FULLSIZE); pos++) {
		cell = board[pos];
		if (isseen(cell))
			cell = (cell & F_FLAGS) | F_WRONG;
		if (ismine(cell))
			cell = (cell & F_FLAGS) | F_REMEMBER;
		board[pos] = cell;
	}

	drawboard();
	drawstatus();
}


/*
 * Search the game parameter table for the current board size and
 * number of mines, and set the index for those parameters so that
 * the statistics can be accessed.  Allocates a new index if necessary.
 */
static void
findindex()
{
	for (index = 0; index < MAXPARAMS; index++) {
		if ((sizeparam[index] == size) && (mineparam[index] == mines))
			return;
	}
	for (index = 0; index < MAXPARAMS; index++) {
		if (sizeparam[index] == 0) {
			sizeparam[index] = size;
			mineparam[index] = mines;
			return;
		}
	}
	fprintf(stderr, "Too many parameters in save file\n");
	exit(1);
}


/*
 * Read in a saved game if available, otherwise start from scratch.
 * Exits if an error is encountered.
 */
static void
readgame(name)
	char	*name;		/* filename */
{
	int	fd;

	fd = -1;
	if (name)
		fd = open(name, 0);

	if (fd < 0) {
		magic = MAGIC;
		size = SIZE;
		mines = (size * size * MINEPERCENT) / 100;
		playing = GR_FALSE;
		return;
	}

	if (read(fd, &st, sizeof(st)) != sizeof(st))
		magic = 0;
	close(fd);

	if ((magic != MAGIC) || (size > MAXSIZE)) {
		fprintf(stderr, "Save file format is incorrect\n");
		exit(1);
	}
}


/*
 * Write the current game to a file.
 * Returns nonzero on an error.
 */
static GR_BOOL
writegame(name)
	char	*name;		/* filename */
{
	int	fd;

	if (name == NULL)
		return GR_TRUE;

	fd = creat(name, 0666);
	if (fd < 0)
		return GR_TRUE;

	if (write(fd, &st, sizeof(st)) != sizeof(st)) {
		close(fd);
		return GR_TRUE;
	}
	close(fd);
	return GR_FALSE;
}

/* END CODE */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -