📄 landmine.c
字号:
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 + -