📄 landmine.c
字号:
/*
* Landmine, the game.
* Written for mini-X by David I. Bell.
*/
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#if UNIX | DOS_DJGPP
#include <fcntl.h>
#include <unistd.h>
#include <time.h>
#endif
#define MWINCLUDECOLORS
#include "nano-X.h"
#define MINSIZE 3 /* minimum size of board */
#define MAXSIZE 30 /* maximum size of board */
#define SIZE 15 /* default size of playing board */
#define MINEPERCENT 15 /* default percentage of mines */
#define SAVEFILE "landmine.save" /* default save file name */
#define MAGIC 649351261 /* magic number in save files */
#define MAXPARAMS 1000 /* maximum different game parameters */
#define FULLSIZE (MAXSIZE + 2) /* board size including borders */
#ifdef __ECOS
/* 240x320 screen values*/
#define BOARDGAP 2 /* millimeter gap around board */
#define RIGHTGAP 2 /* mm gap between board, right side */
#define BUTTONGAP 5 /* mm gap between buttons */
#define STATUSGAP 10 /* mm gap between buttons and status */
#define BUTTONWIDTH 80 /* width of buttons (pixels) */
#define BUTTONHEIGHT 25 /* height of buttons (pixels) */
#define RIGHTSIDE 90 /* pixels to guarantee for right side */
#define BOARDBORDER 2 /* border size around board */
#else
#define BOARDGAP 10 /* millimeter gap around board */
#define RIGHTGAP 15 /* mm gap between board, right side */
#define BUTTONGAP 20 /* mm gap between buttons */
#define STATUSGAP 35 /* mm gap between buttons and status */
#define BUTTONWIDTH 80 /* width of buttons (pixels) */
#define BUTTONHEIGHT 25 /* height of buttons (pixels) */
#define RIGHTSIDE 150 /* pixels to guarantee for right side */
#define BOARDBORDER 2 /* border size around board */
#endif
/*
* Print the number of steps taken.
* This is used twice, and is a macro to guarantee that
* the two printouts match.
*/
#define PRINTSTEPS printline(2, "Steps: %3d\n", steps)
/*
* Typedefs local to this program.
*/
typedef unsigned short CELL; /* cell value */
typedef int POS; /* cell position */
/*
* For defining bitmaps easily.
*/
#define X ((unsigned) 1)
#define _ ((unsigned) 0)
#define BITS(a,b,c,d,e,f,g,h,i) \
(((((((((a*2+b)*2+c)*2+d)*2+e)*2+f)*2+g)*2+h)*2+i) << 7)
static GR_BITMAP twolegs_fg[] = { /* two legs foreground */
BITS(_,_,_,_,_,_,_,_,_),
BITS(_,_,_,X,X,X,_,_,_),
BITS(_,_,_,X,X,X,_,_,_),
BITS(_,_,_,X,X,X,_,_,_),
BITS(_,_,_,_,X,_,_,_,_),
BITS(_,_,X,X,X,X,X,_,_),
BITS(_,X,_,X,_,X,_,X,_),
BITS(_,X,_,X,X,X,_,X,_),
BITS(_,_,_,X,_,X,_,_,_),
BITS(_,_,_,X,_,X,_,_,_),
BITS(_,_,X,X,_,X,X,_,_),
BITS(_,_,_,_,_,_,_,_,_)
};
static GR_BITMAP twolegs_bg[] = { /* two legs background */
BITS(_,_,X,X,X,X,X,_,_),
BITS(_,_,X,X,X,X,X,_,_),
BITS(_,_,X,X,X,X,X,_,_),
BITS(_,_,X,X,X,X,X,_,_),
BITS(_,X,X,X,X,X,X,X,_),
BITS(X,X,X,X,X,X,X,X,X),
BITS(X,X,X,X,_,X,X,X,X),
BITS(X,X,X,X,X,X,X,X,X),
BITS(X,X,X,X,X,X,X,X,X),
BITS(_,X,X,X,X,X,X,X,_),
BITS(_,X,X,X,X,X,X,X,_),
BITS(_,X,X,X,X,X,X,X,_)
};
static GR_BITMAP oneleg_fg[] = { /* one leg foreground */
BITS(_,_,_,_,_,_,_,_,_),
BITS(_,_,_,X,X,X,_,_,_),
BITS(_,_,_,X,X,X,_,_,_),
BITS(_,_,_,X,X,X,_,_,_),
BITS(_,_,_,_,X,_,_,_,_),
BITS(_,_,X,X,X,X,X,_,_),
BITS(_,X,_,X,_,X,_,X,_),
BITS(_,_,_,X,X,X,_,X,_),
BITS(_,_,_,_,_,X,_,_,_),
BITS(_,_,_,_,_,X,_,_,_),
BITS(_,_,_,_,_,X,X,_,_),
BITS(_,_,_,_,_,_,_,_,_),
};
static GR_BITMAP oneleg_bg[] = { /* one leg background */
BITS(_,_,X,X,X,X,X,_,_),
BITS(_,_,X,X,X,X,X,_,_),
BITS(_,_,X,X,X,X,X,_,_),
BITS(_,_,X,X,X,X,X,_,_),
BITS(_,X,X,X,X,X,X,X,_),
BITS(X,X,X,X,X,X,X,X,X),
BITS(X,X,X,X,_,X,X,X,X),
BITS(X,X,X,X,X,X,X,X,X),
BITS(_,_,X,X,X,X,X,X,X),
BITS(_,_,_,_,X,X,X,X,_),
BITS(_,_,_,_,X,X,X,X,_),
BITS(_,_,_,_,X,X,X,X,_)
};
static GR_BITMAP noleg_fg[] = { /* no legs foreground */
BITS(_,_,_,_,_,_,_,_,_),
BITS(_,_,_,X,X,X,_,_,_),
BITS(_,_,_,X,X,X,_,_,_),
BITS(_,_,_,X,X,X,_,_,_),
BITS(_,_,_,_,X,_,_,_,_),
BITS(_,_,X,X,X,X,X,_,_),
BITS(_,X,_,X,_,X,_,X,_),
BITS(_,_,_,X,X,X,_,_,_),
BITS(_,_,_,_,_,_,_,_,_),
BITS(_,_,_,_,_,_,_,_,_),
BITS(_,_,_,_,_,_,_,_,_),
BITS(_,_,_,_,_,_,_,_,_),
};
static GR_BITMAP noleg_bg[] = { /* no legs background */
BITS(_,_,X,X,X,X,X,_,_),
BITS(_,_,X,X,X,X,X,_,_),
BITS(_,_,X,X,X,X,X,_,_),
BITS(_,_,X,X,X,X,X,_,_),
BITS(_,X,X,X,X,X,X,X,_),
BITS(X,X,X,X,X,X,X,X,X),
BITS(X,X,X,X,_,X,X,X,X),
BITS(X,X,X,X,X,X,X,X,X),
BITS(_,_,X,X,X,X,X,_,_),
BITS(_,_,_,_,_,_,_,_,_),
BITS(_,_,_,_,_,_,_,_,_),
BITS(_,_,_,_,_,_,_,_,_)
};
/*
* Components of a cell.
*/
#define F_EMPTY ' ' /* default value for empty square */
#define F_REMEMBER '*' /* character to remember mine */
#define F_WRONG 'X' /* character to remember wrong guess */
#define F_DISPLAY 0xff /* character to be displayed here */
#define F_MINE 0x100 /* TRUE if a mine is here */
#define F_EDGE 0x200 /* TRUE if this is edge of the world */
#define F_OLD 0x400 /* TRUE if been at this square before */
#define F_REACH 0x800 /* TRUE if can reach this square */
#define F_FLAGS 0xff00 /* all flags */
/*
* The status of the game.
* This structure is read and written from the save file.
*/
static struct status { /* status of games */
long s_magic; /* magic number */
short s_playing; /* TRUE if playing a game */
short s_size; /* current size of board */
short s_mines; /* current number of mines on board */
short s_legs; /* number of legs left */
short s_steps; /* number of steps taken this game */
short s_index; /* current game parameter index */
short s_sizeparam[MAXPARAMS]; /* table of size parameters */
short s_mineparam[MAXPARAMS]; /* table of mine parameters */
long s_games0[MAXPARAMS]; /* games finished with no legs */
long s_games1[MAXPARAMS]; /* games finished with one leg */
long s_games2[MAXPARAMS]; /* games finished with two legs */
long s_steps0[MAXPARAMS]; /* steps taken in no leg games */
long s_steps1[MAXPARAMS]; /* steps taken in one leg games */
long s_steps2[MAXPARAMS]; /* steps taken in two leg games */
CELL s_board[FULLSIZE*FULLSIZE]; /* board layout */
} st;
/*
* Definitions to make structure references easy.
*/
#define magic st.s_magic
#define playing st.s_playing
#define size st.s_size
#define mines st.s_mines
#define legs st.s_legs
#define steps st.s_steps
#define index st.s_index
#define sizeparam st.s_sizeparam
#define mineparam st.s_mineparam
#define games0 st.s_games0
#define games1 st.s_games1
#define games2 st.s_games2
#define steps0 st.s_steps0
#define steps1 st.s_steps1
#define steps2 st.s_steps2
#define board st.s_board
#define boardpos(row, col) (((row) * FULLSIZE) + (col))
#define ismine(cell) ((cell) & F_MINE)
#define isedge(cell) ((cell) & F_EDGE)
#define isold(cell) ((cell) & F_OLD)
#define isseen(cell) (((cell) & F_DISPLAY) == F_REMEMBER)
#define isknown(cell) (((cell) & F_DISPLAY) != F_EMPTY)
#define displaychar(cell) ((cell) & F_DISPLAY)
#define badsquare(n) (((n) <= 0) || ((n) > size))
/*
* Offsets for accessing adjacent cells.
*/
static POS steptable[8] = {
FULLSIZE, -FULLSIZE, 1, -1, FULLSIZE-1,
FULLSIZE+1, -FULLSIZE-1, -FULLSIZE+1
};
static GR_WINDOW_ID mainwid; /* main window id */
static GR_WINDOW_ID boardwid; /* board window id */
static GR_WINDOW_ID statwid; /* status display window id */
static GR_WINDOW_ID quitwid; /* window id for quit button */
static GR_WINDOW_ID savewid; /* window id for save button */
static GR_WINDOW_ID newgamewid; /* window id for new game button */
static GR_GC_ID boardgc; /* graphics context for board */
static GR_GC_ID cleargc; /* GC for clearing cell of board */
static GR_GC_ID redgc; /* GC for drawing red */
static GR_GC_ID greengc; /* GC for drawing green */
static GR_GC_ID blackgc; /* GC for drawing black */
static GR_GC_ID delaygc; /* GC for delaying */
static GR_GC_ID statgc; /* GC for status window */
static GR_GC_ID buttongc; /* GC for drawing buttons */
static GR_GC_ID xorgc; /* GC for inverting things */
static GR_SIZE xp; /* pixels for x direction per square */
static GR_SIZE yp; /* pixels for y direction per square */
static GR_SIZE statwidth; /* width of window drawing text in */
static GR_SIZE statheight; /* height of window drawing text in */
static GR_SIZE charheight; /* height of characters */
static GR_COORD charxpos; /* current X position for characters */
static GR_COORD charypos; /* current Y position for characters */
static GR_SCREEN_INFO si; /* window information */
static GR_FONT_INFO fi; /* font information */
static GR_SIZE COLS, ROWS;
static char *savefile; /* filename for saving game */
/*
* Procedures.
*/
static void printline(GR_COORD, char *, ...);
static void newline();
static void delay();
static void dokey();
static void handleevent();
static void doexposure();
static void dobutton();
static void drawbomb();
static void drawstatus();
static void drawbutton();
static void drawboard();
static void drawcell();
static void cellcenter();
static void clearcell();
static void newgame();
static void movetopos();
static void setcursor();
static void togglecell();
static void gameover();
static void readgame();
static void findindex();
static POS findcell();
static GR_BOOL checkpath();
static GR_BOOL writegame();
int
main(argc,argv)
int argc;
char **argv;
{
GR_COORD x;
GR_COORD y;
GR_SIZE width;
GR_SIZE height;
GR_COORD rightx; /* x coordinate for right half stuff */
GR_BOOL setsize; /* TRUE if size of board is set */
GR_BOOL setmines; /* TRUE if number of mines is set */
GR_SIZE newsize = 10; /* desired size of board */
GR_COUNT newmines = 25; /* desired number of mines */
GR_WM_PROPERTIES props;
setmines = GR_FALSE;
setsize = GR_FALSE;
argc--;
argv++;
while ((argc > 0) && (**argv == '-')) {
switch (argv[0][1]) {
case 'm':
if (argc <= 0) {
fprintf(stderr, "Missing mine count\n");
exit(1);
}
argc--;
argv++;
newmines = atoi(*argv);
setmines = GR_TRUE;
break;
case 's':
if (argc <= 0) {
fprintf(stderr, "Missing size\n");
exit(1);
}
argc--;
argv++;
newsize = atoi(*argv);
setsize = GR_TRUE;
break;
default:
fprintf(stderr, "Unknown option \"-%c\"\n",
argv[0][1]);
exit(1);
}
argc--;
argv++;
}
if (argc > 0)
savefile = *argv;
srand(time(0));
readgame(savefile);
if (setsize) {
if ((newsize < MINSIZE) || (newsize > MAXSIZE)) {
fprintf(stderr, "Illegal board size\n");
exit(1);
}
if (newsize != size) {
if (steps && playing) {
fprintf(stderr,
"Cannot change size while game is in progress\n");
exit(1);
}
playing = GR_FALSE;
size = newsize;
if (!playing)
mines = (size * size * MINEPERCENT) / 100;
}
}
if (setmines) {
if ((newmines <= 0) || ((newmines > (size * size) / 2))) {
fprintf(stderr, "Illegal number of mines\n");
exit(1);
}
if (newmines != mines) {
if (steps && playing) {
fprintf(stderr,
"Cannot change mines while game is in progress\n");
exit(1);
}
playing = GR_FALSE;
mines = newmines;
}
}
findindex();
/*
* Parameters of the game have been verified.
* Now open the graphics and play the game.
*/
if (GrOpen() < 0) {
fprintf(stderr, "Cannot open graphics\n");
exit(1);
}
GrReqShmCmds(655360); /* Test by Morten Rolland for shm support */
GrGetScreenInfo(&si);
GrGetFontInfo(0, &fi);
charheight = fi.height;
/*
* Create the main window which will contain all the others.
*/
#if 0
COLS = si.cols - 40;
#else
COLS = si.cols;
#endif
ROWS = si.rows - 80;
mainwid = GrNewWindow(GR_ROOT_WINDOW_ID, 0, 0, COLS, ROWS,
0, BLACK, WHITE);
/* set title */
props.flags = GR_WM_FLAGS_TITLE | GR_WM_FLAGS_PROPS;
props.props = GR_WM_PROPS_APPFRAME | GR_WM_PROPS_CAPTION;
props.title = "Land Mine";
GrSetWMProperties(mainwid, &props);
/*
* Create the board window which lies at the left side.
* Make the board square, and as large as possible while still
* leaving room to the right side for statistics and buttons.
*/
width = COLS - RIGHTSIDE - (si.xdpcm * RIGHTGAP / 10) - BOARDBORDER * 2;
height = (((long) width) * si.ydpcm) / si.xdpcm;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -