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

📄 bs.c

📁 ncurses 库 可能有用酒用 没用就算了 我觉得还可以用
💻 C
📖 第 1 页 / 共 2 页
字号:
	curx = nx % BWIDTH;	cury = ny % BDEPTH;    }}static boolcollidecheck(int b, int y, int x)/* is this location on the selected zboard adjacent to a ship? */{    bool collide;    /* anything on the square */    if ((collide = IS_SHIP(board[b][x][y])) != FALSE)	return (collide);    /* anything on the neighbors */    if (!closepack) {	int i;	for (i = 0; i < 8; i++) {	    int xend, yend;	    yend = y + yincr[i];	    xend = x + xincr[i];	    if (ONBOARD(xend, yend)		&& IS_SHIP(board[b][xend][yend])) {		collide = TRUE;		break;	    }	}    }    return (collide);}static boolcheckplace(int b, ship_t * ss, int vis){    int l, xend, yend;    /* first, check for board edges */    xend = ss->x + (ss->length - 1) * xincr[ss->dir];    yend = ss->y + (ss->length - 1) * yincr[ss->dir];    if (!ONBOARD(xend, yend)) {	if (vis)	    switch (rnd(3)) {	    case 0:		error("Ship is hanging from the edge of the world");		break;	    case 1:		error("Try fitting it on the board");		break;	    case 2:		error("Figure I won't find it if you put it there?");		break;	    }	return (FALSE);    }    for (l = 0; l < ss->length; ++l) {	if (collidecheck(b, ss->y + l * yincr[ss->dir], ss->x + l * xincr[ss->dir])) {	    if (vis)		switch (rnd(3)) {		case 0:		    error("There's already a ship there");		    break;		case 1:		    error("Collision alert!  Aaaaaagh!");		    break;		case 2:		    error("Er, Admiral, what about the other ship?");		    break;		}	    return (FALSE);	}    }    return (TRUE);}static intawinna(void){    int i, j;    ship_t *ss;    for (i = 0; i < 2; ++i) {	ss = (i) ? cpuship : plyship;	for (j = 0; j < SHIPTYPES; ++j, ++ss)	    if (ss->length > ss->hits)		break;	if (j == SHIPTYPES)	    return (OTHER);    }    return (-1);}static ship_t *hitship(int x, int y)/* register a hit on the targeted ship */{    ship_t *sb, *ss;    char sym;    int oldx, oldy;    getyx(stdscr, oldy, oldx);    sb = (turn) ? plyship : cpuship;    if ((sym = board[OTHER][x][y]) == 0)	return ((ship_t *) NULL);    for (ss = sb; ss < sb + SHIPTYPES; ++ss)	if (ss->symbol == sym) {	    if (++ss->hits < ss->length)	/* still afloat? */		return ((ship_t *) NULL);	    else {		/* sunk! */		int i, j;		if (!closepack)		    for (j = -1; j <= 1; j++) {			int bx = ss->x + j * xincr[(ss->dir + 2) % 8];			int by = ss->y + j * yincr[(ss->dir + 2) % 8];			for (i = -1; i <= ss->length; ++i) {			    int x1, y1;			    x1 = bx + i * xincr[ss->dir];			    y1 = by + i * yincr[ss->dir];			    if (ONBOARD(x1, y1)) {				hits[turn][x1][y1] = MARK_MISS;				if (turn % 2 == PLAYER) {				    cgoto(y1, x1);#ifdef A_COLOR				    if (has_colors())					attron(COLOR_PAIR(COLOR_GREEN));#endif /* A_COLOR */				    (void) addch(MARK_MISS);#ifdef A_COLOR				    attrset(0);#endif /* A_COLOR */				} else {				    pgoto(y1, x1);				    (void) addch(SHOWSPLASH);				}			    }			}		    }		for (i = 0; i < ss->length; ++i) {		    int x1 = ss->x + i * xincr[ss->dir];		    int y1 = ss->y + i * yincr[ss->dir];		    hits[turn][x1][y1] = ss->symbol;		    if (turn % 2 == PLAYER) {			cgoto(y1, x1);			(void) addch((chtype) (ss->symbol));		    } else {			pgoto(y1, x1);#ifdef A_COLOR			if (has_colors())			    attron(COLOR_PAIR(COLOR_RED));#endif /* A_COLOR */			(void) addch(SHOWHIT);#ifdef A_COLOR			attrset(0);#endif /* A_COLOR */		    }		}		(void) move(oldy, oldx);		return (ss);	    }	}    (void) move(oldy, oldx);    return ((ship_t *) NULL);}static boolplyturn(void){    ship_t *ss;    bool hit;    NCURSES_CONST char *m = NULL;    prompt(1, "Where do you want to shoot? ", "");    for (;;) {	(void) getcoord(COMPUTER);	if (hits[PLAYER][curx][cury]) {	    prompt(1, "You shelled this spot already! Try again.", "");	    beep();	} else	    break;    }    hit = IS_SHIP(board[COMPUTER][curx][cury]);    hits[PLAYER][curx][cury] = (hit ? MARK_HIT : MARK_MISS);    cgoto(cury, curx);#ifdef A_COLOR    if (has_colors()) {	if (hit)	    attron(COLOR_PAIR(COLOR_RED));	else	    attron(COLOR_PAIR(COLOR_GREEN));    }#endif /* A_COLOR */    (void) addch((chtype) hits[PLAYER][curx][cury]);#ifdef A_COLOR    attrset(0);#endif /* A_COLOR */    prompt(1, "You %s.", hit ? "scored a hit" : "missed");    if (hit && (ss = hitship(curx, cury))) {	switch (rnd(5)) {	case 0:	    m = " You sank my %s!";	    break;	case 1:	    m = " I have this sinking feeling about my %s....";	    break;	case 2:	    m = " My %s has gone to Davy Jones's locker!";	    break;	case 3:	    m = " Glub, glub -- my %s is headed for the bottom!";	    break;	case 4:	    m = " You'll pick up survivors from my %s, I hope...!";	    break;	}	(void) printw(m, ss->name);	(void) beep();	return (awinna() == -1);    }    return (hit);}static intsgetc(const char *s){    const char *s1;    int ch;    (void) refresh();    for (;;) {	ch = getch();	if (islower(ch))	    ch = toupper(ch);	if (ch == CTRLC)	    uninitgame(0);	for (s1 = s; *s1 && ch != *s1; ++s1)	    continue;	if (*s1) {	    (void) addch((chtype) ch);	    (void) refresh();	    return (ch);	}    }}static voidrandomfire(int *px, int *py)/* random-fire routine -- implements simple diagonal-striping strategy */{    static int turncount = 0;    static int srchstep = BEGINSTEP;    static int huntoffs;	/* Offset on search strategy */    int ypossible[BWIDTH * BDEPTH], xpossible[BWIDTH * BDEPTH], nposs;    int ypreferred[BWIDTH * BDEPTH], xpreferred[BWIDTH * BDEPTH], npref;    int x, y, i;    if (turncount++ == 0)	huntoffs = rnd(srchstep);    /* first, list all possible moves */    nposs = npref = 0;    for (x = 0; x < BWIDTH; x++)	for (y = 0; y < BDEPTH; y++)	    if (!hits[COMPUTER][x][y]) {		xpossible[nposs] = x;		ypossible[nposs] = y;		nposs++;		if (((x + huntoffs) % srchstep) != (y % srchstep)) {		    xpreferred[npref] = x;		    ypreferred[npref] = y;		    npref++;		}	    }    if (npref) {	i = rnd(npref);	*px = xpreferred[i];	*py = ypreferred[i];    } else if (nposs) {	i = rnd(nposs);	*px = xpossible[i];	*py = ypossible[i];	if (srchstep > 1)	    --srchstep;    } else {	error("No moves possible?? Help!");	ExitProgram(EXIT_FAILURE);	/*NOTREACHED */    }}#define S_MISS	0#define S_HIT	1#define S_SUNK	-1static intcpufire(int x, int y)/* fire away at given location */{    bool hit, sunk;    ship_t *ss = NULL;    hits[COMPUTER][x][y] = (hit = (board[PLAYER][x][y])) ? MARK_HIT : MARK_MISS;    (void) mvprintw(PROMPTLINE, 0,		    "I shoot at %c%d. I %s!", y + 'A', x, hit ? "hit" :		    "miss");    if ((sunk = (hit && (ss = hitship(x, y)))) != 0)	(void) printw(" I've sunk your %s", ss->name);    (void) clrtoeol();    pgoto(y, x);#ifdef A_COLOR    if (has_colors()) {	if (hit)	    attron(COLOR_PAIR(COLOR_RED));	else	    attron(COLOR_PAIR(COLOR_GREEN));    }#endif /* A_COLOR */    (void) addch((chtype) (hit ? SHOWHIT : SHOWSPLASH));#ifdef A_COLOR    attrset(0);#endif /* A_COLOR */    return ((hit ? (sunk ? S_SUNK : S_HIT) : S_MISS) ? TRUE : FALSE);}/* * This code implements a fairly irregular FSM, so please forgive the rampant * unstructuredness below. The five labels are states which need to be held * between computer turns. */static boolcputurn(void){#define POSSIBLE(x, y)	(ONBOARD(x, y) && !hits[COMPUTER][x][y])#define RANDOM_FIRE	0#define RANDOM_HIT	1#define HUNT_DIRECT	2#define FIRST_PASS	3#define REVERSE_JUMP	4#define SECOND_PASS	5    static int next = RANDOM_FIRE;    static bool used[4];    static ship_t ts;    int navail, x, y, d, n;    int hit = S_MISS;    switch (next) {    case RANDOM_FIRE:		/* last shot was random and missed */      refire:	randomfire(&x, &y);	if (!(hit = cpufire(x, y)))	    next = RANDOM_FIRE;	else {	    ts.x = x;	    ts.y = y;	    ts.hits = 1;	    next = (hit == S_SUNK) ? RANDOM_FIRE : RANDOM_HIT;	}	break;    case RANDOM_HIT:		/* last shot was random and hit */	used[E / 2] = used[S / 2] = used[W / 2] = used[N / 2] = FALSE;	/* FALLTHROUGH */    case HUNT_DIRECT:		/* last shot hit, we're looking for ship's long axis */	for (d = navail = 0; d < 4; d++) {	    x = ts.x + xincr[d * 2];	    y = ts.y + yincr[d * 2];	    if (!used[d] && POSSIBLE(x, y))		navail++;	    else		used[d] = TRUE;	}	if (navail == 0)	/* no valid places for shots adjacent... */	    goto refire;	/* ...so we must random-fire */	else {	    for (d = 0, n = rnd(navail) + 1; n; n--)		while (used[d])		    d++;	    assert(d <= 4);	    used[d] = FALSE;	    x = ts.x + xincr[d * 2];	    y = ts.y + yincr[d * 2];	    assert(POSSIBLE(x, y));	    if (!(hit = cpufire(x, y)))		next = HUNT_DIRECT;	    else {		ts.x = x;		ts.y = y;		ts.dir = d * 2;		ts.hits++;		next = (hit == S_SUNK) ? RANDOM_FIRE : FIRST_PASS;	    }	}	break;    case FIRST_PASS:		/* we have a start and a direction now */	x = ts.x + xincr[ts.dir];	y = ts.y + yincr[ts.dir];	if (POSSIBLE(x, y) && (hit = cpufire(x, y))) {	    ts.x = x;	    ts.y = y;	    ts.hits++;	    next = (hit == S_SUNK) ? RANDOM_FIRE : FIRST_PASS;	} else	    next = REVERSE_JUMP;	break;    case REVERSE_JUMP:		/* nail down the ship's other end */	d = ts.dir + 4;	x = ts.x + ts.hits * xincr[d];	y = ts.y + ts.hits * yincr[d];	if (POSSIBLE(x, y) && (hit = cpufire(x, y))) {	    ts.x = x;	    ts.y = y;	    ts.dir = d;	    ts.hits++;	    next = (hit == S_SUNK) ? RANDOM_FIRE : SECOND_PASS;	} else	    next = RANDOM_FIRE;	break;    case SECOND_PASS:		/* kill squares not caught on first pass */	x = ts.x + xincr[ts.dir];	y = ts.y + yincr[ts.dir];	if (POSSIBLE(x, y) && (hit = cpufire(x, y))) {	    ts.x = x;	    ts.y = y;	    ts.hits++;	    next = (hit == S_SUNK) ? RANDOM_FIRE : SECOND_PASS;	    break;	} else	    next = RANDOM_FIRE;	break;    }    /* check for continuation and/or winner */    if (salvo) {	(void) refresh();	(void) sleep(1);    }    if (awinna() != -1)	return (FALSE);#ifdef DEBUG    (void) mvprintw(PROMPTLINE + 2, 0,		    "New state %d, x=%d, y=%d, d=%d",		    next, x, y, d);#endif /* DEBUG */    return ((hit) ? TRUE : FALSE);}static intplayagain(void){    int j;    ship_t *ss;    for (ss = cpuship; ss < cpuship + SHIPTYPES; ss++)	for (j = 0; j < ss->length; j++) {	    cgoto(ss->y + j * yincr[ss->dir], ss->x + j * xincr[ss->dir]);	    (void) addch((chtype) ss->symbol);	}    if (awinna())	++cpuwon;    else	++plywon;    j = 18 + strlen(name);    if (plywon >= 10)	++j;    if (cpuwon >= 10)	++j;    (void) mvprintw(1, (COLWIDTH - j) / 2,		    "%s: %d     Computer: %d", name, plywon, cpuwon);    prompt(2, (awinna())? "Want to be humiliated again, %s [yn]? "	   : "Going to give me a chance for revenge, %s [yn]? ", name);    return (sgetc("YN") == 'Y');}static voiddo_options(int c, char *op[]){    register int i;    if (c > 1) {	for (i = 1; i < c; i++) {	    switch (op[i][0]) {	    default:	    case '?':		(void) fprintf(stderr, "Usage: battle [-s | -b] [-c]\n");		(void) fprintf(stderr, "\tWhere the options are:\n");		(void) fprintf(stderr, "\t-s : play a salvo game\n");		(void) fprintf(stderr, "\t-b : play a blitz game\n");		(void) fprintf(stderr, "\t-c : ships may be adjacent\n");		ExitProgram(EXIT_FAILURE);		break;	    case '-':		switch (op[i][1]) {		case 'b':		    blitz = 1;		    if (salvo == 1) {			(void) fprintf(stderr,				       "Bad Arg: -b and -s are mutually exclusive\n");			ExitProgram(EXIT_FAILURE);		    }		    break;		case 's':		    salvo = 1;		    if (blitz == 1) {			(void) fprintf(stderr,				       "Bad Arg: -s and -b are mutually exclusive\n");			ExitProgram(EXIT_FAILURE);		    }		    break;		case 'c':		    closepack = 1;		    break;		default:		    (void) fprintf(stderr,				   "Bad arg: type \"%s ?\" for usage message\n",				   op[0]);		    ExitProgram(EXIT_FAILURE);		}	    }	}    }}static intscount(int who){    register int i, shots;    register ship_t *sp;    if (who)	sp = cpuship;		/* count cpu shots */    else	sp = plyship;		/* count player shots */    for (i = 0, shots = 0; i < SHIPTYPES; i++, sp++) {	if (sp->hits >= sp->length)	    continue;		/* dead ship */	else	    shots++;    }    return (shots);}intmain(int argc, char *argv[]){    setlocale(LC_ALL, "");    do_options(argc, argv);    intro();    do {	initgame();	while (awinna() == -1) {	    if (!blitz) {		if (!salvo) {		    if (turn)			(void) cputurn();		    else			(void) plyturn();		} else {		    register int i;		    i = scount(turn);		    while (i--) {			if (turn) {			    if (cputurn() && awinna() != -1)				i = 0;			} else {			    if (plyturn() && awinna() != -1)				i = 0;			}		    }		}	    } else		while (turn ? cputurn() : plyturn())		    continue;	    turn = OTHER;	}    } while	(playagain());    uninitgame(0);    /*NOTREACHED */}/* bs.c ends here */

⌨️ 快捷键说明

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