?? bs.c
字號:
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 */
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -