📄 knight.c
字号:
/* * Knight's Tour - a brain game * * The original of this game was anonymous. It had an unbelievably bogus * interface, you actually had to enter square coordinates! Redesign by * Eric S. Raymond <esr@snark.thyrsus.com> July 22 1995. Mouse support * added September 20th 1995. * * $Id: knight.c,v 1.26 2002/10/19 22:11:24 tom Exp $ */#include <test.priv.h>/* board size */#define BDEPTH 8#define BWIDTH 8/* where to start the instructions */#define INSTRY 2#define INSTRX 35/* corner of board */#define BOARDY 2#define BOARDX 0/* notification line */#define NOTIFYY 21/* virtual color values */#define TRAIL_COLOR 1#define PLUS_COLOR 2#define MINUS_COLOR 3#define CX(x) (2 + 4 * (x))#define CY(y) (1 + 2 * (y))#define cellmove(y, x) wmove(boardwin, CY(y), CX(x))#define CXINV(x) (((x) - 1) / 4)#define CYINV(y) (((y) - 2) / 2)typedef struct { short x, y;} cell;static WINDOW *boardwin; /* the board window */static WINDOW *helpwin; /* the help window */static WINDOW *msgwin; /* the message window */static cell history[BDEPTH * BWIDTH + 1]; /* choice history */static chtype minus = '-'; /* possible-move character */static chtype oldch;static chtype plus = '+'; /* cursor hot-spot character */static chtype trail = '#'; /* trail character */static int movecount; /* count of moves so far */static int trialcount; /* count of trials so far */static short board[BDEPTH][BWIDTH]; /* the squares *//* *INDENT-OFF* */static const struct { int y; int x;} offsets[] = { { 2, 1 }, { 1, 2 }, { -1, 2 }, { -2, 1 }, { -2, -1 }, { -1, -2 }, { 1, -2 }, { 2, -1 },};/* *INDENT-ON* */static voidinit_program(void){ setlocale(LC_ALL, ""); srand((unsigned) getpid()); initscr(); cbreak(); /* immediate char return */ noecho(); /* no immediate echo */ boardwin = newwin(BDEPTH * 2 + 1, BWIDTH * 4 + 1, BOARDY, BOARDX); helpwin = newwin(0, 0, INSTRY, INSTRX); msgwin = newwin(1, INSTRX - 1, NOTIFYY, 0); scrollok(msgwin, TRUE); keypad(boardwin, TRUE); if (has_colors()) { int bg = COLOR_BLACK; start_color();#if HAVE_USE_DEFAULT_COLORS if (use_default_colors() == OK) bg = -1;#endif (void) init_pair(TRAIL_COLOR, COLOR_CYAN, bg); (void) init_pair(PLUS_COLOR, COLOR_RED, bg); (void) init_pair(MINUS_COLOR, COLOR_GREEN, bg); trail |= COLOR_PAIR(TRAIL_COLOR); plus |= COLOR_PAIR(PLUS_COLOR); minus |= COLOR_PAIR(MINUS_COLOR); }#ifdef NCURSES_MOUSE_VERSION (void) mousemask(BUTTON1_CLICKED, (mmask_t *) NULL);#endif /* NCURSES_MOUSE_VERSION */ oldch = minus;}static voidhelp1(void)/* game explanation -- initial help screen */{ (void) waddstr(helpwin, "Knight's move is a solitaire puzzle. Your\n"); (void) waddstr(helpwin, "objective is to visit each square of the \n"); (void) waddstr(helpwin, "chessboard exactly once by making knight's\n"); (void) waddstr(helpwin, "moves (one square right or left followed \n"); (void) waddstr(helpwin, "by two squares up or down, or two squares \n"); (void) waddstr(helpwin, "right or left followed by one square up or\n"); (void) waddstr(helpwin, "down). You may start anywhere.\n\n"); (void) waddstr(helpwin, "Use arrow keys to move the cursor around.\n"); (void) waddstr(helpwin, "When you want to move your knight to the \n"); (void) waddstr(helpwin, "cursor location, press <space> or Enter.\n"); (void) waddstr(helpwin, "Illegal moves will be rejected with an \n"); (void) waddstr(helpwin, "audible beep.\n\n"); (void) waddstr(helpwin, "The program will detect if you solve the\n"); (void) waddstr(helpwin, "puzzle; also inform you when you run out\n"); (void) waddstr(helpwin, "of legal moves.\n\n"); (void) mvwaddstr(helpwin, NOTIFYY - INSTRY, 0, "Press `?' to go to keystroke help.");}static voidhelp2(void)/* keystroke help screen */{ (void) waddstr(helpwin, "Possible moves are shown with `-'.\n\n"); (void) waddstr(helpwin, "You can move around with the arrow keys or\n"); (void) waddstr(helpwin, "with the rogue/hack movement keys. Other\n"); (void) waddstr(helpwin, "commands allow you to undo moves or redraw.\n"); (void) waddstr(helpwin, "Your mouse may work; try left-button to\n"); (void) waddstr(helpwin, "move to the square under the pointer.\n\n"); (void) waddstr(helpwin, "x,q -- exit y k u 7 8 9\n"); (void) waddstr(helpwin, "r -- redraw screen \\|/ \\|/ \n"); (void) waddstr(helpwin, "bksp -- undo move h-+-l 4-+-6\n"); (void) waddstr(helpwin, "a -- autojump /|\\ /|\\ \n"); (void) waddstr(helpwin, " b j n 1 2 3\n"); (void) waddstr(helpwin, "\nYou can place your knight on the selected\n"); (void) waddstr(helpwin, "square with spacebar, Enter, or the keypad\n"); (void) waddstr(helpwin, "center key. Use F/B to review the path.\n"); (void) mvwaddstr(helpwin, NOTIFYY - INSTRY, 0, "Press `?' to go to game explanation");}static voidshow_help(bool * keyhelp){ werase(helpwin); if (*keyhelp) { help1(); *keyhelp = FALSE; } else { help2(); *keyhelp = TRUE; } wrefresh(helpwin);}static boolchksqr(int r1, int c1){ if ((r1 < 0) || (r1 > BDEPTH - 1)) return (FALSE); if ((c1 < 0) || (c1 > BWIDTH - 1)) return (FALSE); return ((!board[r1][c1]) ? TRUE : FALSE);}static boolchkmoves(int rw, int col)/* check to see if valid moves are available */{ unsigned n; for (n = 0; n < SIZEOF(offsets); n++) if (chksqr(rw + offsets[n].y, col + offsets[n].x)) return (TRUE); return (FALSE);}static voiddosquares(void){ int i, j; mvaddstr(0, 20, "KNIGHT'S MOVE -- a logical solitaire"); move(BOARDY, BOARDX); waddch(boardwin, ACS_ULCORNER); for (j = 0; j < 7; j++) { waddch(boardwin, ACS_HLINE); waddch(boardwin, ACS_HLINE); waddch(boardwin, ACS_HLINE); waddch(boardwin, ACS_TTEE); } waddch(boardwin, ACS_HLINE); waddch(boardwin, ACS_HLINE); waddch(boardwin, ACS_HLINE); waddch(boardwin, ACS_URCORNER); for (i = 1; i < BDEPTH; i++) { move(BOARDY + i * 2 - 1, BOARDX); waddch(boardwin, ACS_VLINE); for (j = 0; j < BWIDTH; j++) { waddch(boardwin, ' '); waddch(boardwin, ' '); waddch(boardwin, ' '); waddch(boardwin, ACS_VLINE); } move(BOARDY + i * 2, BOARDX); waddch(boardwin, ACS_LTEE); for (j = 0; j < BWIDTH - 1; j++) { waddch(boardwin, ACS_HLINE); waddch(boardwin, ACS_HLINE); waddch(boardwin, ACS_HLINE); waddch(boardwin, ACS_PLUS); } waddch(boardwin, ACS_HLINE); waddch(boardwin, ACS_HLINE); waddch(boardwin, ACS_HLINE); waddch(boardwin, ACS_RTEE); } move(BOARDY + i * 2 - 1, BOARDX); waddch(boardwin, ACS_VLINE); for (j = 0; j < BWIDTH; j++) { waddch(boardwin, ' '); waddch(boardwin, ' '); waddch(boardwin, ' '); waddch(boardwin, ACS_VLINE); } move(BOARDY + i * 2, BOARDX); waddch(boardwin, ACS_LLCORNER); for (j = 0; j < BWIDTH - 1; j++) { waddch(boardwin, ACS_HLINE); waddch(boardwin, ACS_HLINE); waddch(boardwin, ACS_HLINE); waddch(boardwin, ACS_BTEE); } waddch(boardwin, ACS_HLINE); waddch(boardwin, ACS_HLINE); waddch(boardwin, ACS_HLINE); waddch(boardwin, ACS_LRCORNER);}static voidmark_possibles(int prow, int pcol, chtype mark){ unsigned n; for (n = 0; n < SIZEOF(offsets); n++) { if (chksqr(prow + offsets[n].y, pcol + offsets[n].x)) { cellmove(prow + offsets[n].y, pcol + offsets[n].x); waddch(boardwin, mark); } }}static voidfind_next_move(int *y, int *x){ unsigned j, k; int found = -1; int first = -1; int next = 0; int oldy, oldx; int newy, newx; if (movecount > 1) { oldy = history[movecount - 1].y; oldx = history[movecount - 1].x; for (j = 0; j < SIZEOF(offsets) * 2; j++) { k = j % SIZEOF(offsets); newy = oldy + offsets[k].y; newx = oldx + offsets[k].x; if (chksqr(newy, newx)) { if (first < 0) first = k; if (newy == *y && newx == *x) { found = k; } else if (found >= 0) { next = k; break; } } } if (found < 0) next = first; if (next >= 0) { *y = oldy + offsets[next].y; *x = oldx + offsets[next].x; } } else { beep(); }}static voidunmarkcell(int row, int column){ cellmove(row, column); waddch(boardwin, '\b'); waddch(boardwin, ' '); waddch(boardwin, minus); waddch(boardwin, ' ');}static voidmarkcell(chtype tchar, int row, int column){ cellmove(row, column); waddch(boardwin, '\b'); waddch(boardwin, tchar); waddch(boardwin, tchar); waddch(boardwin, tchar);}static voiddrawmove(chtype tchar, int oldy, int oldx, int row, int column)/* place the stars, update board & currents */{ if (movecount <= 1) { int i, j; for (i = 0; i < BDEPTH; i++) { for (j = 0; j < BWIDTH; j++) { if (movecount == 0) { unmarkcell(i, j); } else { cellmove(i, j); if (winch(boardwin) == minus) waddch(boardwin, movecount ? ' ' : minus); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -