#include #include #include #include #include /* * each board position has: * ' ' : empty * r, w : a red/white standard piece * R, W : a red/white King piece */ char board[8][8]; void index2rc(int index, int *row, int *col) { *row = (index - 1) / 4; *col = ((index - 1) % 4) * 2; if (*row % 2 == 0) { (*col)++; } } int rc2index(int row, int col) { if (row % 2 == 0) { col--; } col /= 2; return row * 4 + col + 1; } void read_board(int r, int w) { int i, j, row, col, index; for (i = 0; i < 8; i++) { for (j = 0; j < 8; j++) { board[i][j] = ' '; } } for (i = 0; i < r; i++) { scanf("%d", &index); index2rc((index < 0) ? -index : index, &row, &col); board[row][col] = (index < 0) ? 'R' : 'r'; } for (i = 0; i < w; i++) { scanf("%d", &index); index2rc((index < 0) ? -index : index, &row, &col); board[row][col] = (index < 0) ? 'W' : 'w'; } } void print_board(void) { int i, j; for (i = 0; i < 8; i++) { for (j = 0; j < 8; j++) { putchar(board[i][j]); } putchar('\n'); } putchar('\n'); } int parse_moves(char *buffer, int *moves) { int n = 0; char *p; p = buffer; while ((p = strtok(p, "-\n"))) { moves[n++] = atoi(p); p = 0; } return n; } /* check if the piece at (row,col) can jump in a given direction */ typedef enum { NE, NW, SE, SW } Direction; int row_delta[4] = {-1, -1, 1, 1}; int col_delta[4] = {-1, 1, -1, 1}; int check_jump_dir(int row, int col, char side, Direction dir) { int r, c, r2, c2; int king; assert(tolower(board[row][col]) == side); king = isupper((int)board[row][col]); r = row + row_delta[dir]; c = col + col_delta[dir]; r2 = r + row_delta[dir]; c2 = c + col_delta[dir]; return ((king || (side == 'r' && r > row) || (side == 'w' && r < row)) && /* jump in right direction */ (0 <= r2 && r2 < 8 && 0 <= c2 && c2 < 8) && /* jump in bound */ (board[r][c] != ' ') && /* something to jump over */ (tolower(board[r][c]) != side) && /* jump over opponent */ (board[r2][c2] == ' ')); /* destination empty */ } int check_jump(int row, int col, char side) { return check_jump_dir(row, col, side, NE) || check_jump_dir(row, col, side, NW) || check_jump_dir(row, col, side, SE) || check_jump_dir(row, col, side, SW); } int can_jump(char side) { int i, j; for (i = 0; i < 8; i++) { for (j = 0; j < 8; j++) { if (tolower(board[i][j]) == side && check_jump(i, j, side)) { return 1; } } } return 0; } void promote(int r, int c, char side) { if ((side == 'r' && r == 7) || (side == 'w' && r == 0)) { board[r][c] = toupper(board[r][c]); assert(board[r][c] == toupper(side)); } } /* check whether it's a valid adjacent move */ int check_adj_move(int *moves, int num_moves, char side) { int r1, r2, c1, c2; int king; /* must be of length 2 */ if (num_moves != 2) { return 0; } /* check that we cannot jump instead */ if (can_jump(side)) { return 0; } index2rc(moves[0], &r1, &c1); index2rc(moves[1], &r2, &c2); king = isupper((int)board[r1][c1]); /* check that moves[0] contains the right piece, and moves[1] is empty */ if (tolower(board[r1][c1]) != side || board[r2][c2] != ' ') { return 0; } /* check that moves[0] and moves[1] are adjacent */ if ((r1 - r2 != -1 && r1 - r2 != 1) || (c1 - c2 != -1 && c1 - c2 != 1)) { return 0; } /* check that the direction is valid */ if (!king && ((side == 'r' && r2 < r1) || (side == 'w' && r2 > r1))) { return 0; } /* make the move, check for promotion */ board[r2][c2] = board[r1][c1]; board[r1][c1] = ' '; promote(r2, c2, side); return 1; } int check_jump_move(int *moves, int num_moves, char side) { int result, r1, r2, rm, c1, c2, cm, i; int king; for (i = 0; i < num_moves-1; i++) { index2rc(moves[i], &r1, &c1); index2rc(moves[i+1], &r2, &c2); rm = (r1 + r2) / 2; cm = (c1 + c2) / 2; king = isupper((int)board[r1][c1]); /* check that moves[i] contains the right piece, and moves[i+1] is empty */ if (tolower(board[r1][c1]) != side || board[r2][c2] != ' ') { return 0; } /* check that moves[i] and moves[i+1] are two apart, with an opposite piece in between */ if ((r1 - r2 != -2 && r1 - r2 != 2) || (c1 - c2 != -2 && c1 - c2 != 2) || tolower(board[rm][cm]) != ((side == 'r') ? 'w' : 'r')) { return 0; } /* check that the direction is valid */ if (!king && ((side == 'r' && r2 < r1) || (side == 'w' && r2 > r1))) { return 0; } /* make the move, and return the result of the recursion */ board[r2][c2] = board[r1][c1]; board[r1][c1] = board[rm][cm] = ' '; } /* check that there is no more jump available at the end */ result = !check_jump(r2, c2, side); /* change to king if necessary, has to be done after check_jump */ promote(r2, c2, side); return result; } int main(void) { int r, w; char move_buffer[1024]; /* way more than enough */ int moves[12], num_moves; int m, i, error; char side; while (scanf("%d %d", &r, &w) == 2 && r > 0) { error = 0; read_board(r, w); scanf("%d", &m); scanf("%s\n", move_buffer); side = tolower(move_buffer[0]); assert(side == 'r' || side == 'w'); for (i = 0; i < m; i++) { fgets(move_buffer, 1024, stdin); num_moves = parse_moves(move_buffer, moves); if (!error && !check_adj_move(moves, num_moves, side) && !check_jump_move(moves, num_moves, side)) { printf("Move %d is invalid\n", i+1); error = 1; } /* print_board(); */ side = (side == 'r') ? 'w' : 'r'; } if (!error) { printf("All moves valid\n"); } } return 0; }