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

📄 landmine.c

📁 一个嵌入式操作系统(microwindows)的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	if ((kp->wid != boardwid) || !playing)		return;	switch (kp->ch) {		case ' ':			/* remember or forget mine */			togglecell(findcell(kp->x, kp->y));			break;	}}/* * Redraw the board. */static voiddrawboard(void){	GR_COORD	row;	GR_COORD	col;	for (row = 1; row < size; row++) {		GrLine(boardwid, boardgc, 0, row * yp - 1, size * xp - 1,			row * yp - 1);		GrLine(boardwid, boardgc, row * xp - 1, 0,			row * xp - 1, size * yp - 1);	}	for (row = 0; row < FULLSIZE; row++) {		for (col = 0; col < FULLSIZE; col++) {			drawcell(boardpos(row, col));		}	}}/* * Draw a cell on the board. */static voiddrawcell(POS pos){	GR_COORD	x;	GR_COORD	y;	GR_SIZE		chwidth;	GR_SIZE		chheight;	GR_SIZE		chbase;	CELL		cell;	GR_CHAR		ch;	cell = board[pos];	if (!isknown(cell))		return;	ch = displaychar(cell);	if (ch == F_WRONG) {		drawbomb(pos, greengc, GR_FALSE);		return;	}	if (isold(cell)) {		clearcell(pos);		cellcenter(pos, &x, &y);		GrGetGCTextSize(boardgc, &ch, 1, GR_TFASCII, &chwidth,			&chheight, &chbase);		GrText(boardwid, boardgc, x - chwidth / 2 + 1,			y + chheight / 2, &ch, 1, GR_TFBOTTOM);		return;	}	drawbomb(pos, redgc, GR_FALSE);}/* * Clear a particular cell. */static voidclearcell(POS pos){	GR_COORD	row;	GR_COORD	col;	row = pos / FULLSIZE;	col = pos % FULLSIZE;	GrFillRect(boardwid, cleargc, col * xp - xp, row * yp - yp,		xp - 1, yp - 1);}/* * Draw a bomb in a window using the specified GC. * The bomb is animated and the terminal is beeped if necessary. */static voiddrawbomb(POS pos, GR_GC_ID gc, GR_BOOL animate)	/*POS		pos;		position to draw bomb at */	/*GR_GC_ID	gc;		GC for drawing (red or green) */	/*GR_BOOL		animate;	TRUE to animate the bomb */{	GR_COORD	x;	GR_COORD	y;	GR_COUNT	count;	if (animate)		write(1, "\007", 1);	cellcenter(pos, &x, &y);	count = (animate ? 8 : 1);	for (;;) {		GrFillEllipse(boardwid, gc, x, y, xp / 2 - 3, yp / 2 - 3);		if (--count == 0)			return;		delay();		clearcell(pos);		delay();	}}/* * Draw a button which has a specified label string centered in it. */static voiddrawbutton(GR_WINDOW_ID window, char *label){	GR_SIZE		width;	GR_SIZE		height;	GR_SIZE		base;	GrGetGCTextSize(buttongc, label, strlen(label), GR_TFASCII, &width,		&height, &base);	GrText(window, buttongc, (BUTTONWIDTH - width) / 2,		(BUTTONHEIGHT - height) / 2 + height - 1,		label, -1, GR_TFBOTTOM);}/* * Set the cursor as appropriate. * The cursor changes depending on the number of legs left. */static voidsetcursor(void){	GR_BITMAP	*fgbits;	/* bitmap for foreground */	GR_BITMAP	*bgbits;	/* bitmap for background */	switch (legs) {		case 0:			fgbits = noleg_fg;			bgbits = noleg_bg;			break;		case 1:			fgbits = oneleg_fg;			bgbits = oneleg_bg;			break;		default:			fgbits = twolegs_fg;			bgbits = twolegs_bg;			break;	}	GrSetCursor(boardwid, 9, 12, 4, 6, WHITE, BLACK, fgbits, bgbits);}/* * Delay for a while so that something can be seen. * This is done by drawing a large rectangle over the window using a mode * of XOR with the value of 0, (which does nothing except waste time). */static voiddelay(void){	GR_COUNT	i;	for (i = 0; i < 1; i++) {		GrFillRect(boardwid, delaygc, 0, 0, xp * size - 1,			yp * size - 1);		GrFlush();	}}/* * Calculate the coordinates of the center of a cell on the board. * The coordinates are relative to the origin of the board window. */static voidcellcenter(POS pos, GR_COORD *retx, GR_COORD *rety){	*retx = (pos % FULLSIZE) * xp - 1 - xp / 2;	*rety = (pos / FULLSIZE) * yp - 1 - yp / 2;}/* * Draw the status information in the status window. */static voiddrawstatus(void){	long	score;	long	allsteps;	long	games;	score = 0;	games = games0[index];	allsteps = steps0[index];	score += games1[index];	games += games1[index];	allsteps += steps1[index];	score += games2[index] * 2;	games += games2[index];	allsteps += steps2[index];	printline(0, "Size:   %2d\n", size);	printline(1, "Mines: %3d\n", mines);	PRINTSTEPS;	printline(3, "Legs:    %d\n", legs);	printline(5, "Won games:  %3d\n", games2[index]);	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 voidnewline(void){	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 POSfindcell(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 voidnewgame(void){	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_BOOLcheckpath(POS pos){	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 voidmovetopos(POS newpos){	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 voidtogglecell(POS pos){	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 voidgameover(void){	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 voidfindindex(void){	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 voidreadgame(char *name){	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_BOOLwritegame(char *name){	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 + -