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

📄 landmine.c

📁 开放源码实时操作系统源码.
💻 C
📖 第 1 页 / 共 3 页
字号:
	if (height > ROWS /* - y * 2*/) {
		height = ROWS - BOARDBORDER * 2;
		width = (((long) height) * si.xdpcm) / si.ydpcm;
	}
	xp = width / size;
	yp = height / size;

	width = xp * size - 1;
	height = yp * size - 1;
	x = BOARDBORDER;
	y = (ROWS - height) / 2;

	rightx = x + width + (si.xdpcm * RIGHTGAP / 10);
	boardwid = GrNewWindow(mainwid, x, y, width, height, BOARDBORDER,
		BLUE, WHITE);
	/*
	 * Create the buttons.
	 */
	x = rightx;
	y = (si.ydpcm * BOARDGAP / 10);
	quitwid = GrNewWindow(mainwid, x, y, BUTTONWIDTH, BUTTONHEIGHT,
		1, RED, WHITE);

	y += (si.ydpcm * BUTTONGAP / 10);
	savewid = GrNewWindow(mainwid, x, y, BUTTONWIDTH, BUTTONHEIGHT,
		1, GREEN, WHITE);

	y += (si.ydpcm * BUTTONGAP / 10);
	newgamewid = GrNewWindow(mainwid, x, y, BUTTONWIDTH, BUTTONHEIGHT,
		1, GREEN, WHITE);

	/*
	 * Create the statistics window.
	 */
	x = rightx;
	y += (si.ydpcm * STATUSGAP / 10);
	width = COLS - x;
	height = ROWS - y;
	statwid = GrNewWindow(mainwid, x, y, width, height, 0,
		0, 0);
	statwidth = width;
	statheight = height;

	/*
	 * Create the GC for drawing the board.
	 */
	boardgc = GrNewGC();
	cleargc = GrNewGC();
	delaygc = GrNewGC();
	redgc = GrNewGC();
	greengc = GrNewGC();
	statgc = GrNewGC();
	blackgc = GrNewGC();
	buttongc = GrNewGC();
	xorgc = GrNewGC();
	GrSetGCBackground(boardgc, BLUE);
	GrSetGCForeground(cleargc, BLUE);
	GrSetGCForeground(redgc, RED);
	GrSetGCForeground(greengc, GREEN);
	GrSetGCForeground(statgc, GRAY);
	GrSetGCForeground(delaygc, BLACK);
	GrSetGCForeground(blackgc, BLACK);
	GrSetGCMode(delaygc, GR_MODE_XOR);
	GrSetGCMode(xorgc, GR_MODE_XOR);
	GrSetGCUseBackground(boardgc, GR_FALSE);
	GrSetGCUseBackground(buttongc, GR_FALSE);

	GrSelectEvents(mainwid, GR_EVENT_MASK_CLOSE_REQ);

	GrSelectEvents(boardwid, GR_EVENT_MASK_EXPOSURE |
		GR_EVENT_MASK_BUTTON_DOWN | GR_EVENT_MASK_KEY_DOWN);

	GrSelectEvents(statwid, GR_EVENT_MASK_EXPOSURE);

	GrSelectEvents(quitwid, GR_EVENT_MASK_EXPOSURE |
		GR_EVENT_MASK_BUTTON_DOWN);

	GrSelectEvents(newgamewid, GR_EVENT_MASK_EXPOSURE |
		GR_EVENT_MASK_BUTTON_DOWN);

	GrSelectEvents(savewid, GR_EVENT_MASK_EXPOSURE |
		GR_EVENT_MASK_BUTTON_DOWN);

	setcursor();

	GrMapWindow(mainwid);
	GrMapWindow(boardwid);
	GrMapWindow(statwid);
	GrMapWindow(quitwid);
	GrMapWindow(savewid);
	GrMapWindow(newgamewid);

	if (!playing)
		newgame();

	while (GR_TRUE) {
		GR_EVENT event;

		GrGetNextEvent(&event);
		handleevent(&event);
	}
}


/*
 * Read the next event and handle it.
 */
static void
handleevent(GR_EVENT *ep)
{
	switch (ep->type) {
		case GR_EVENT_TYPE_BUTTON_DOWN:
			dobutton(&ep->button);
			break;

		case GR_EVENT_TYPE_EXPOSURE:
			doexposure(&ep->exposure);
			break;

		case GR_EVENT_TYPE_KEY_DOWN:
			dokey(&ep->keystroke);
			break;

		case GR_EVENT_TYPE_CLOSE_REQ:
			GrClose();
			exit(0);
	}
}


/*
 * Handle exposure events.
 */
static void
doexposure(ep)
	GR_EVENT_EXPOSURE	*ep;
{
	if (ep->wid == boardwid) {
		drawboard();
		return;
	}

	if (ep->wid == statwid) {
		drawstatus();
		return;
	}

	if (ep->wid == quitwid) {
		drawbutton(quitwid, "QUIT");
		return;
	}

	if (ep->wid == savewid) {
		drawbutton(savewid, "SAVE GAME");
		return;
	}

	if (ep->wid == newgamewid) {
		drawbutton(newgamewid, "NEW GAME");
		return;
	}
}


/*
 * Here when we get a button down event.
 */
static void
dobutton(bp)
	GR_EVENT_BUTTON		*bp;
{
	if (bp->wid == boardwid) {
		movetopos(findcell(bp->x, bp->y));
		return;
	}

	if (bp->wid == quitwid) {
		GrFillRect(quitwid, xorgc, 0, 0, BUTTONWIDTH, BUTTONHEIGHT);
		GrFlush();
		if (savefile)
			writegame(savefile);
		GrClose();
		exit(0);
	}

	if (bp->wid == savewid) {
		GrFillRect(savewid, xorgc, 0, 0, BUTTONWIDTH, BUTTONHEIGHT);
		GrFlush();
		if (savefile == NULL)
			savefile = SAVEFILE;
		if (writegame(savefile))
			write(1, "\007", 1);
		else
			delay();
		GrFillRect(savewid, xorgc, 0, 0, BUTTONWIDTH, BUTTONHEIGHT);
	}

	if (bp->wid == newgamewid) {
		GrFillRect(newgamewid, xorgc, 0, 0, BUTTONWIDTH, BUTTONHEIGHT);
		GrFlush();
		/*if (playing)
			write(1, "\007", 1);
		else {*/
			newgame();
			delay();
		/*}*/
		GrFillRect(newgamewid, xorgc, 0, 0, BUTTONWIDTH, BUTTONHEIGHT);
	}
}


/*
 * Here when we get a keypress in a window.
 */
static void
dokey(kp)
	GR_EVENT_KEYSTROKE	*kp;
{
	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 void
drawboard()
{
	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 void
drawcell(pos)
	POS		pos;		/* position to be drawn */
{
	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 void
clearcell(pos)
	POS		pos;		/* position to be cleared */
{
	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 void
drawbomb(pos, gc, 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 void
drawbutton(window, label)
	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 void
setcursor()
{
	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 void
delay()
{
	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 void
cellcenter(pos, retx, rety)
	POS		pos;		/* position to find center of */
	GR_COORD	*retx;		/* returned X coordinate */
	GR_COORD	*rety;		/* returned Y coordinate */
{
	*retx = (pos % FULLSIZE) * xp - 1 - xp / 2;
	*rety = (pos / FULLSIZE) * yp - 1 - yp / 2;
}


/*
 * Draw the status information in the status window.
 */
static void
drawstatus()
{
	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]);

⌨️ 快捷键说明

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