P5380 [THUPC2019] 鸭棋 题解

一道大模拟题。

分析

做这道题之前,我们首先需要捋一捋思路。

对于每一个操作,我们需要做的就是下面几点:

  1. 判断是否可行
  2. 如可行,则移动棋子
  3. 判断是否移除了对方的棋子
  4. 判断是否形成了将军局面
  5. 判断是否结束了游戏

就下面五点。

可行性

首先我们分析一下有哪些情况会导致操作不可行:

  1. 游戏已经结束。
    这个在所有操作之前进行一个判断即可。
  2. 移动的起止点不在棋盘内。
    这个在移动之前判断即可。
  3. 开始移动的地方没有己方棋子。
    同上。
  4. 移动的目的地已经有了己方棋子。
    同上。
  5. 移动的方式不符合棋子的可达位置。
    对于每一种棋子分类判断。
  6. (象、马、鸭)被绊住。
    与上方情况一起判断。

所有的情况只有这六种。

将军与否

这个与上面判断目的地是否符合棋子的可达位置相似。
但是,我采用的是判断一个王是否能被棋子吃掉的方法,与大部分人的不太一样,注意坐标的不同。
(就这个让我调了好长时间)

游戏结束

一旦有一方的王被移除,那么游戏就结束了。
这个判断移除的棋子类型的时候就顺便判断了。


实现

下面是代码实现部分:

定义

我们将七种棋子用数字表示,红方为1-7,蓝方为11-17。

顺序就是按照题目给的顺序,从1到7分别是:王士象马车鸭兵。

初始化

我一开始以为棋盘长10宽9,就按照这样写了下去,结果反了,所以注意这里的坐标问题。

void initMap() { memset(base, 0, sizeof(base)); base[4][0] = 1; base[4][9] = 11; base[3][0] = base[5][0] = 2; base[3][9] = base[5][9] = 12; base[2][0] = base[6][0] = 3; base[2][9] = base[6][9] = 13; base[1][0] = base[7][0] = 4; base[1][9] = base[7][9] = 14; base[0][0] = base[8][0] = 5; base[0][9] = base[8][9] = 15; base[0][2] = base[8][2] = 6; base[0][7] = base[8][7] = 16; base[0][3] = base[2][3] = base[4][3] = base[6][3] = base[8][3] = 7; base[0][6] = base[2][6] = base[4][6] = base[6][6] = base[8][6] = 17; }

是否越过边界

棋盘长为9,。宽为10,坐标从 (0,0) 开始,到 (8,9) 结束。

void checkOut() { bool flag = false; if (sx < 0)flag = true; if (sx > 8)flag = true; if (sy < 0)flag = true; if (sy > 9)flag = true; if (tx < 0)flag = true; if (tx > 8)flag = true; if (ty < 0)flag = true; if (ty > 9)flag = true; if (flag) { puts("Invalid command"); isInvalid = true; } }

(其实本来可以写紧凑些的)

移动

我们这里直接对棋子的类型进行分析。

首先,我们需要判断我们的起止点是否合法,即起始点有没有棋子、目的地有没有己方棋子什么的。

if (base[sx][sy] / 10 != side) { puts("Invalid command"); isInvalid = true; return; } else if (base[sx][sy] == 0) { puts("Invalid command"); isInvalid = true; return; } else if (base[tx][ty] / 10 == side && base[tx][ty] != 0) { puts("Invalid command"); isInvalid = true; return; }

(其实本来可以写紧凑些的)

然后就是对每一种棋子的类型分开讨论:

王的可达范围是与其相邻的四个格子:

[pic here]

判定方法比较简单:

if (type == 1) { if (abs(sx - tx) + abs(sy - ty) > 1) { puts("Invalid command"); isInvalid = true; return; } }

士的可达范围为其四角的格子:

[pic here]

判定方法也很简单:

else if (type == 2) { if (abs(sx - tx) != 1 || abs(sy - ty) != 1) { puts("Invalid command"); isInvalid = true; return; } }

象在没有被绊住的情况下可以到达其四角距其两格的格子:

[pic here]

这时候需要判定两种情况,一是目的地不合法,二是目的地合法,但被绊住不能动。

else if (type == 3) { if (abs(sx - tx) != 2 || abs(sy - ty) != 2) { puts("Invalid command"); isInvalid = true; return; } if (base[(sx + tx) / 2][(sy + ty) / 2] != 0) { puts("Invalid command"); isInvalid = true; return; } }

车能在当前行和当前列中随意移动,直到遇到了一个棋子。
如果遇到的是敌方棋子,那就可以吃掉对方;
如果遇到的是己方棋子就会被判定不合法。

(这里就不放图了)

首先,因为我们有了起止点,我们就可以先判断车所要到的地方是否是己方棋子。如果是的话就直接判定不合法。
然后我们需要判定起止点是否在同一行或同一列上,否则就不合法。
最后,我们从起始点向目的地扫,看中间有没有棋子,任何一方的都算,因为车不能跨过棋子。

else if (type == 5) { if (sx != tx && sy != ty) { puts("Invalid command"); isInvalid = true; return; } bool collide = false; if (sx != tx) { int tmpx = min(sx, tx); for (int i = tmpx + 1; i < max(sx, tx); i++) { if (base[i][sy] != 0) { collide = true; break; } } } else if (sy != ty) { int tmpy = min(sy, ty); for (int i = tmpy + 1; i < max(sy, ty); i++) { if (base[sx][i] != 0) { collide = true; break; } } } if (collide) { puts("Invalid command"); isInvalid = true; return; } }

马可以到的位置是日字形的地方,同时还需要注意绊住的情况:

[pic here]

else if (type == 4) { if (!(abs(sx - tx) == 2 && abs(sy - ty) == 1) && !(abs(sx - tx) == 1 && abs(sy - ty) == 2)) { puts("Invalid command"); isInvalid = true; return; } if (abs(sx - tx) > abs(sy - ty)) { if (base[sx + (tx - sx) / 2][sy] != 0) { puts("Invalid command"); isInvalid = true; return; } } else { if (base[sx][sy + (ty - sy) / 2] != 0) { puts("Invalid command"); isInvalid = true; return; } } }

鸭的判定是最麻烦的一步,因为其需要注意的地方比较多。(主要是绊脚的地方多)
鸭可以走到的地方如下图:

[pic here]

else if (type == 6) { if (!(abs(sx - tx) == 3 && abs(sy - ty) == 2) && !(abs(sx - tx) == 2 && abs(sy - ty) == 3)) { puts("Invalid command"); isInvalid = true; return; } int kx = (tx - sx > 0) ? 1 : -1; int ky = (ty - sy > 0) ? 1 : -1; if (abs(sx - tx) > abs(sy - ty)) { if (base[sx + kx][sy] != 0 || base[sx + 2 * kx][sy + ky] != 0) { puts("Invalid command"); isInvalid = true; return; } } else { if (base[sx][sy + ky] != 0 || base[sx + kx][sy + 2 * ky] != 0) { puts("Invalid command"); isInvalid = true; return; } } }

兵能走到的地方是与其八联通的格子:

[pic here]

else if (type == 7) { if (abs(sx - tx) > 1 || abs(sy - ty) > 1) { puts("Invalid command"); isInvalid = true; return; } }

判定是否将军

我们判断是否将军的函数其实与移动的函数差不多,但是我不会写(雾)

我这里用的是判断王能不能被攻击到的方法。

一个让我调了很长时间的一点就是,我这里还需要转化一下参考系,所以绊脚的位置不一样了。

bool checkMate(int k) { int x = 0, y = 0; for (int i = 0; i <= 8; i++) for (int j = 0; j <= 9; j++) if (base[i][j] == (k ^ 1) * 10 + 1) { x = i; y = j; break; } bool flag = false; for (int i = x + 1; i <= 8; i++) { if (base[i][y] == k * 10 + 5) { flag = true; break; } else if (base[i][y] != 0)break; } for (int i = x - 1; i >= 0; i--) { if (base[i][y] == k * 10 + 5) { flag = true; break; } else if (base[i][y] != 0)break; } for (int i = y + 1; i <= 9; i++) { if (base[x][i] == k * 10 + 5) { flag = true; break; } else if (base[x][i] != 0)break; } for (int i = y - 1; i >= 0; i--) { if (base[x][i] == k * 10 + 5) { flag = true; break; } else if (base[x][i] != 0)break; } if (flag)return flag; if (x <= 7 && base[x + 1][y] == k * 10 + 1)flag = true; if (y <= 8 && base[x][y + 1] == k * 10 + 1)flag = true; if (x >= 1 && base[x - 1][y] == k * 10 + 1)flag = true; if (y >= 1 && base[x][y - 1] == k * 10 + 1)flag = true; if (flag)return flag; if (x <= 7 && y <= 8 && base[x + 1][y + 1] == k * 10 + 2)flag = true; if (x >= 1 && y <= 8 && base[x - 1][y + 1] == k * 10 + 2)flag = true; if (x <= 7 && y >= 1 && base[x + 1][y - 1] == k * 10 + 2)flag = true; if (x >= 1 && y >= 1 && base[x - 1][y - 1] == k * 10 + 2)flag = true; if (flag)return flag; if (x <= 7 && y <= 8 && base[x + 1][y + 1] == k * 10 + 7)flag = true; if (x >= 1 && y <= 8 && base[x - 1][y + 1] == k * 10 + 7)flag = true; if (x <= 7 && y >= 1 && base[x + 1][y - 1] == k * 10 + 7)flag = true; if (x >= 1 && y >= 1 && base[x - 1][y - 1] == k * 10 + 7)flag = true; if (x <= 7 && base[x + 1][y] == k * 10 + 7)flag = true; if (y <= 8 && base[x - 1][y] == k * 10 + 7)flag = true; if (x >= 1 && base[x][y + 1] == k * 10 + 7)flag = true; if (y >= 1 && base[x][y - 1] == k * 10 + 7)flag = true; if (flag)return flag; if (x <= 6 && y <= 8 && base[x + 2][y + 1] == k * 10 + 4 && base[x + 1][y + 1] == 0)flag = true; if (x >= 2 && y <= 8 && base[x - 2][y + 1] == k * 10 + 4 && base[x - 1][y + 1] == 0)flag = true; if (x <= 6 && y >= 1 && base[x + 2][y - 1] == k * 10 + 4 && base[x + 1][y - 1] == 0)flag = true; if (x >= 2 && y >= 1 && base[x - 2][y - 1] == k * 10 + 4 && base[x - 1][y - 1] == 0)flag = true; if (x <= 7 && y <= 7 && base[x + 1][y + 2] == k * 10 + 4 && base[x + 1][y + 1] == 0)flag = true; if (x >= 1 && y <= 7 && base[x - 1][y + 2] == k * 10 + 4 && base[x - 1][y + 1] == 0)flag = true; if (x <= 7 && y >= 2 && base[x + 1][y - 2] == k * 10 + 4 && base[x + 1][y - 1] == 0)flag = true; if (x >= 1 && y >= 2 && base[x - 1][y - 2] == k * 10 + 4 && base[x - 1][y - 1] == 0)flag = true; if (flag)return flag; if (x <= 6 && y <= 7 && base[x + 2][y + 2] == k * 10 + 3 && base[x + 1][y + 1] == 0)flag = true; if (x >= 2 && y <= 7 && base[x - 2][y + 2] == k * 10 + 3 && base[x - 1][y + 1] == 0)flag = true; if (x <= 6 && y >= 2 && base[x + 2][y - 2] == k * 10 + 3 && base[x + 1][y - 1] == 0)flag = true; if (x >= 2 && y >= 2 && base[x - 2][y - 2] == k * 10 + 3 && base[x - 1][y - 1] == 0)flag = true; if (flag)return flag; if (x <= 5 && y <= 7 && base[x + 3][y + 2] == k * 10 + 6 && base[x + 1][y + 1] == 0 && base[x + 2][y + 2] == 0)flag = true; if (x >= 3 && y <= 7 && base[x - 3][y + 2] == k * 10 + 6 && base[x - 1][y + 1] == 0 && base[x - 2][y + 2] == 0)flag = true; if (x <= 5 && y >= 2 && base[x + 3][y - 2] == k * 10 + 6 && base[x + 1][y - 1] == 0 && base[x + 2][y - 2] == 0)flag = true; if (x >= 3 && y >= 2 && base[x - 3][y - 2] == k * 10 + 6 && base[x - 1][y - 1] == 0 && base[x - 2][y - 2] == 0)flag = true; if (x <= 6 && y <= 6 && base[x + 2][y + 3] == k * 10 + 6 && base[x + 1][y + 1] == 0 && base[x + 2][y + 2] == 0)flag = true; if (x >= 2 && y <= 6 && base[x - 2][y + 3] == k * 10 + 6 && base[x - 1][y + 1] == 0 && base[x - 2][y + 2] == 0)flag = true; if (x <= 6 && y >= 3 && base[x + 2][y - 3] == k * 10 + 6 && base[x + 1][y - 1] == 0 && base[x + 2][y - 2] == 0)flag = true; if (x >= 2 && y >= 3 && base[x - 2][y - 3] == k * 10 + 6 && base[x - 1][y - 1] == 0 && base[x - 2][y - 2] == 0)flag = true; return flag; }

然后就没有大的操作了。
判断是否结束游戏就看被移除的棋子类型即可。
输出的时候直接switch case就可以了。


全部加起来:

C++:

#define _CRT_SECURE_NO_WARNINGS #include<bits/stdc++.h> using namespace std; #define ll long long int base[20][20]; bool isCaptured = false; bool isInvalid = false; bool isCheckmate = false; int side = 0; int sx, sy, tx, ty; int knockOut = 0; int cnt = 0; void initMap() { memset(base, 0, sizeof(base)); base[4][0] = 1; base[4][9] = 11; base[3][0] = base[5][0] = 2; base[3][9] = base[5][9] = 12; base[2][0] = base[6][0] = 3; base[2][9] = base[6][9] = 13; base[1][0] = base[7][0] = 4; base[1][9] = base[7][9] = 14; base[0][0] = base[8][0] = 5; base[0][9] = base[8][9] = 15; base[0][2] = base[8][2] = 6; base[0][7] = base[8][7] = 16; base[0][3] = base[2][3] = base[4][3] = base[6][3] = base[8][3] = 7; base[0][6] = base[2][6] = base[4][6] = base[6][6] = base[8][6] = 17; } void init() { isInvalid = false; isCheckmate = false; knockOut = 0; } void checkOut() { bool flag = false; if (sx < 0)flag = true; if (sx > 8)flag = true; if (sx < 0)flag = true; if (sy > 9)flag = true; if (tx < 0)flag = true; if (tx > 8)flag = true; if (tx < 0)flag = true; if (ty > 9)flag = true; if (flag) { puts("Invalid command"); isInvalid = true; } } void move() { if (base[sx][sy] / 10 != side) { puts("Invalid command"); isInvalid = true; return; } else if (base[sx][sy] == 0) { puts("Invalid command"); isInvalid = true; return; } else if (base[tx][ty] / 10 == side && base[tx][ty] != 0) { puts("Invalid command"); isInvalid = true; return; } int type = base[sx][sy] % 10; if (type == 1) { if (abs(sx - tx) + abs(sy - ty) > 1) { puts("Invalid command"); isInvalid = true; return; } } else if (type == 2) { if (abs(sx - tx) != 1 || abs(sy - ty) != 1) { puts("Invalid command"); isInvalid = true; return; } } else if (type == 3) { if (abs(sx - tx) != 2 || abs(sy - ty) != 2) { puts("Invalid command"); isInvalid = true; return; } if (base[(sx + tx) / 2][(sy + ty) / 2] != 0) { puts("Invalid command"); isInvalid = true; return; } } else if (type == 4) { if (!(abs(sx - tx) == 2 && abs(sy - ty) == 1) && !(abs(sx - tx) == 1 && abs(sy - ty) == 2)) { puts("Invalid command"); isInvalid = true; return; } if (abs(sx - tx) > abs(sy - ty)) { if (base[sx + (tx - sx) / 2][sy] != 0) { puts("Invalid command"); isInvalid = true; return; } } else { if (base[sx][sy + (ty - sy) / 2] != 0) { puts("Invalid command"); isInvalid = true; return; } } } else if (type == 5) { if (sx != tx && sy != ty) { puts("Invalid command"); isInvalid = true; return; } bool collide = false; if (sx != tx) { int tmpx = min(sx, tx); for (int i = tmpx + 1; i < max(sx, tx); i++) { if (base[i][sy] != 0) { collide = true; break; } } } else if (sy != ty) { int tmpy = min(sy, ty); for (int i = tmpy + 1; i < max(sy, ty); i++) { if (base[sx][i] != 0) { collide = true; break; } } } if (collide) { puts("Invalid command"); isInvalid = true; return; } } else if (type == 6) { if (!(abs(sx - tx) == 3 && abs(sy - ty) == 2) && !(abs(sx - tx) == 2 && abs(sy - ty) == 3)) { puts("Invalid command"); isInvalid = true; return; } int kx = (tx - sx > 0) ? 1 : -1; int ky = (ty - sy > 0) ? 1 : -1; if (abs(sx - tx) > abs(sy - ty)) { if (base[sx + kx][sy] != 0 || base[sx + 2 * kx][sy + ky] != 0) { puts("Invalid command"); isInvalid = true; return; } } else { if (base[sx][sy + ky] != 0 || base[sx + kx][sy + 2 * ky] != 0) { puts("Invalid command"); isInvalid = true; return; } } } else if (type == 7) { if (abs(sx - tx) > 1 || abs(sy - ty) > 1) { puts("Invalid command"); isInvalid = true; return; } } knockOut = base[tx][ty]; base[tx][ty] = base[sx][sy]; base[sx][sy] = 0; } bool checkMate(int k) { int x = 0, y = 0; for (int i = 0; i <= 8; i++) for (int j = 0; j <= 9; j++) if (base[i][j] == (k ^ 1) * 10 + 1) { x = i; y = j; break; } bool flag = false; for (int i = x + 1; i <= 8; i++) { if (base[i][y] == k * 10 + 5) { flag = true; break; } else if (base[i][y] != 0)break; } for (int i = x - 1; i >= 0; i--) { if (base[i][y] == k * 10 + 5) { flag = true; break; } else if (base[i][y] != 0)break; } for (int i = y + 1; i <= 9; i++) { if (base[x][i] == k * 10 + 5) { flag = true; break; } else if (base[x][i] != 0)break; } for (int i = y - 1; i >= 0; i--) { if (base[x][i] == k * 10 + 5) { flag = true; break; } else if (base[x][i] != 0)break; } if (flag)return flag; if (x <= 7 && base[x + 1][y] == k * 10 + 1)flag = true; if (y <= 8 && base[x][y + 1] == k * 10 + 1)flag = true; if (x >= 1 && base[x - 1][y] == k * 10 + 1)flag = true; if (y >= 1 && base[x][y - 1] == k * 10 + 1)flag = true; if (flag)return flag; if (x <= 7 && y <= 8 && base[x + 1][y + 1] == k * 10 + 2)flag = true; if (x >= 1 && y <= 8 && base[x - 1][y + 1] == k * 10 + 2)flag = true; if (x <= 7 && y >= 1 && base[x + 1][y - 1] == k * 10 + 2)flag = true; if (x >= 1 && y >= 1 && base[x - 1][y - 1] == k * 10 + 2)flag = true; if (flag)return flag; if (x <= 7 && y <= 8 && base[x + 1][y + 1] == k * 10 + 7)flag = true; if (x >= 1 && y <= 8 && base[x - 1][y + 1] == k * 10 + 7)flag = true; if (x <= 7 && y >= 1 && base[x + 1][y - 1] == k * 10 + 7)flag = true; if (x >= 1 && y >= 1 && base[x - 1][y - 1] == k * 10 + 7)flag = true; if (x <= 7 && base[x + 1][y] == k * 10 + 7)flag = true; if (y <= 8 && base[x - 1][y] == k * 10 + 7)flag = true; if (x >= 1 && base[x][y + 1] == k * 10 + 7)flag = true; if (y >= 1 && base[x][y - 1] == k * 10 + 7)flag = true; if (flag)return flag; if (x <= 6 && y <= 8 && base[x + 2][y + 1] == k * 10 + 4 && base[x + 1][y + 1] == 0)flag = true; if (x >= 2 && y <= 8 && base[x - 2][y + 1] == k * 10 + 4 && base[x - 1][y + 1] == 0)flag = true; if (x <= 6 && y >= 1 && base[x + 2][y - 1] == k * 10 + 4 && base[x + 1][y - 1] == 0)flag = true; if (x >= 2 && y >= 1 && base[x - 2][y - 1] == k * 10 + 4 && base[x - 1][y - 1] == 0)flag = true; if (x <= 7 && y <= 7 && base[x + 1][y + 2] == k * 10 + 4 && base[x + 1][y + 1] == 0)flag = true; if (x >= 1 && y <= 7 && base[x - 1][y + 2] == k * 10 + 4 && base[x - 1][y + 1] == 0)flag = true; if (x <= 7 && y >= 2 && base[x + 1][y - 2] == k * 10 + 4 && base[x + 1][y - 1] == 0)flag = true; if (x >= 1 && y >= 2 && base[x - 1][y - 2] == k * 10 + 4 && base[x - 1][y - 1] == 0)flag = true; if (flag)return flag; if (x <= 6 && y <= 7 && base[x + 2][y + 2] == k * 10 + 3 && base[x + 1][y + 1] == 0)flag = true; if (x >= 2 && y <= 7 && base[x - 2][y + 2] == k * 10 + 3 && base[x - 1][y + 1] == 0)flag = true; if (x <= 6 && y >= 2 && base[x + 2][y - 2] == k * 10 + 3 && base[x + 1][y - 1] == 0)flag = true; if (x >= 2 && y >= 2 && base[x - 2][y - 2] == k * 10 + 3 && base[x - 1][y - 1] == 0)flag = true; if (flag)return flag; if (x <= 5 && y <= 7 && base[x + 3][y + 2] == k * 10 + 6 && base[x + 1][y + 1] == 0 && base[x + 2][y + 2] == 0)flag = true; if (x >= 3 && y <= 7 && base[x - 3][y + 2] == k * 10 + 6 && base[x - 1][y + 1] == 0 && base[x - 2][y + 2] == 0)flag = true; if (x <= 5 && y >= 2 && base[x + 3][y - 2] == k * 10 + 6 && base[x + 1][y - 1] == 0 && base[x + 2][y - 2] == 0)flag = true; if (x >= 3 && y >= 2 && base[x - 3][y - 2] == k * 10 + 6 && base[x - 1][y - 1] == 0 && base[x - 2][y - 2] == 0)flag = true; if (x <= 6 && y <= 6 && base[x + 2][y + 3] == k * 10 + 6 && base[x + 1][y + 1] == 0 && base[x + 2][y + 2] == 0)flag = true; if (x >= 2 && y <= 6 && base[x - 2][y + 3] == k * 10 + 6 && base[x - 1][y + 1] == 0 && base[x - 2][y + 2] == 0)flag = true; if (x <= 6 && y >= 3 && base[x + 2][y - 3] == k * 10 + 6 && base[x + 1][y - 1] == 0 && base[x + 2][y - 2] == 0)flag = true; if (x >= 2 && y >= 3 && base[x - 2][y - 3] == k * 10 + 6 && base[x - 1][y - 1] == 0 && base[x - 2][y - 2] == 0)flag = true; return flag; } void write() { switch (base[tx][ty]) { case 1: { printf("red captain;"); break; } case 2: { printf("red guard;"); break; } case 3: { printf("red elephant;"); break; } case 4: { printf("red horse;"); break; } case 5: { printf("red car;"); break; } case 6: { printf("red duck;"); break; } case 7: { printf("red soldier;"); break; } case 11: { printf("blue captain;"); break; } case 12: { printf("blue guard;"); break; } case 13: { printf("blue elephant;"); break; } case 14: { printf("blue horse;"); break; } case 15: { printf("blue car;"); break; } case 16: { printf("blue duck;"); break; } case 17: { printf("blue soldier;"); break; } } switch (knockOut) { case 0: { printf("NA;"); break; } case 1: { printf("red captain;"); break; } case 2: { printf("red guard;"); break; } case 3: { printf("red elephant;"); break; } case 4: { printf("red horse;"); break; } case 5: { printf("red car;"); break; } case 6: { printf("red duck;"); break; } case 7: { printf("red soldier;"); break; } case 11: { printf("blue captain;"); break; } case 12: { printf("blue guard;"); break; } case 13: { printf("blue elephant;"); break; } case 14: { printf("blue horse;"); break; } case 15: { printf("blue car;"); break; } case 16: { printf("blue duck;"); break; } case 17: { printf("blue soldier;"); break; } } if (knockOut == 1 || knockOut == 11)isCaptured = true; if (!isCaptured && isCheckmate)printf("yes;"); else printf("no;"); if (isCaptured)printf("yes\n"); else printf("no\n"); } int main() { initMap(); int Q; scanf("%d", &Q); for (int i = 1; i <= Q; i++) { init(); scanf("%d%d%d%d", &sy, &sx, &ty, &tx); cnt++; if (isCaptured) { puts("Invalid command"); continue; } checkOut(); move(); if (isInvalid)continue; isCheckmate = checkMate(0) || checkMate(1); write(); side ^= 1; } return 0; }

C#:

using System; namespace Main { class Map { public int[,] m = new int[20, 20]; public int side; public bool isCaptured; public bool isInvalid; public bool isCheckmate; public int knockOut; public int sx, sy, tx, ty; public Map() { Array.Clear(m, 0, m.Length); side = 0; isCaptured = false; isInvalid = false; isCheckmate = false; knockOut = 0; sx = 0; sy = 0; tx = 0; ty = 0; } public void Init() { m[4, 0] = 1; m[4, 9] = 11; m[3, 0] = m[5, 0] = 2; m[3, 9] = m[5, 9] = 12; m[2, 0] = m[6, 0] = 3; m[2, 9] = m[6, 9] = 13; m[1, 0] = m[7, 0] = 4; m[1, 9] = m[7, 9] = 14; m[0, 0] = m[8, 0] = 5; m[0, 9] = m[8, 9] = 15; m[0, 2] = m[8, 2] = 6; m[0, 7] = m[8, 7] = 16; m[0, 3] = m[2, 3] = m[4, 3] = m[6, 3] = m[8, 3] = 7; m[0, 6] = m[2, 6] = m[4, 6] = m[6, 6] = m[8, 6] = 17; } public void Clear() { isInvalid = false; isCheckmate = false; knockOut = 0; } public void CheckOut() { bool flag = false; if (sx < 0 || sx > 8) flag = true; if (sy < 0 || sy > 9) flag = true; if (tx < 0 || tx > 8) flag = true; if (ty < 0 || ty > 9) flag = true; if (flag) { Console.WriteLine("Invalid command"); isInvalid = true; } } public void Move() { if (m[sx, sy] / 10 != side) { Console.WriteLine("Invalid command"); isInvalid = true; return; } else if (m[sx, sy] == 0) { Console.WriteLine("Invalid command"); isInvalid = true; return; } else if (m[tx, ty] / 10 == side && m[tx, ty] != 0) { Console.WriteLine("Invalid command"); isInvalid = true; return; } int type = m[sx, sy] % 10; if (type == 1) { if (Math.Abs(sx - tx) + Math.Abs(sy - ty) > 1) { Console.WriteLine("Invalid command"); isInvalid = true; return; } } else if (type == 2) { if (Math.Abs(sx - tx) != 1 || Math.Abs(sy - ty) != 1) { Console.WriteLine("Invalid command"); isInvalid = true; return; } } else if (type == 3) { if (Math.Abs(sx - tx) != 2 || Math.Abs(sy - ty) != 2) { Console.WriteLine("Invalid command"); isInvalid = true; return; } if (m[(sx + tx) / 2, (sy + ty) / 2] != 0) { Console.WriteLine("Invalid command"); isInvalid = true; return; } } else if (type == 4) { if (!(Math.Abs(sx - tx) == 2 && Math.Abs(sy - ty) == 1) && !(Math.Abs(sx - tx) == 1 && Math.Abs(sy - ty) == 2)) { Console.WriteLine("Invalid command"); isInvalid = true; return; } if (Math.Abs(sx - tx) > Math.Abs(sy - ty)) { if (m[sx + (tx - sx) / 2, sy] != 0) { Console.WriteLine("Invalid command"); isInvalid = true; return; } } else { if (m[sx, sy + (ty - sy) / 2] != 0) { Console.WriteLine("Invalid command"); isInvalid = true; return; } } } else if (type == 5) { if (sx != tx && sy != ty) { Console.WriteLine("Invalid command"); isInvalid = true; return; } bool RookCollide = false; if (sx != tx) { for (int i = Math.Min(sx, tx) + 1; i < Math.Max(sx, tx); i++) { if (m[i, sy] != 0) { RookCollide = true; break; } } } else { for (int i = Math.Min(sy, ty) + 1; i < Math.Max(sy, ty); i++) { if (m[sx, i] != 0) { RookCollide = true; break; } } } if (RookCollide) { Console.WriteLine("Invalid command"); isInvalid = true; return; } } else if (type == 6) { if (!(Math.Abs(sx - tx) == 3 && Math.Abs(sy - ty) == 2) && !(Math.Abs(sx - tx) == 2 && Math.Abs(sy - ty) == 3)) { Console.WriteLine("Invalid command"); isInvalid = true; return; } int kx = (tx - sx > 0) ? 1 : -1; int ky = (ty - sy > 0) ? 1 : -1; if (Math.Abs(sx - tx) > Math.Abs(sy - ty)) { if (m[sx + kx, sy] != 0 || m[sx + 2 * kx, sy + ky] != 0) { Console.WriteLine("Invalid command"); isInvalid = true; return; } } else { if (m[sx, sy + ky] != 0 || m[sx + kx, sy + 2 * ky] != 0) { Console.WriteLine("Invalid command"); isInvalid = true; return; } } } else if (type == 7) { if (Math.Abs(sx - tx) > 1 || Math.Abs(sy - ty) > 1) { Console.WriteLine("Invalid command"); isInvalid = true; return; } } knockOut = m[tx, ty]; m[tx, ty] = m[sx, sy]; m[sx, sy] = 0; } public bool CheckMate(int k) { int x = 0, y = 0; for (int i = 0; i <= 8; i++) { for (int j = 0; j <= 9; j++) { if (m[i, j] == (k ^ 1) * 10 + 1) { x = i; y = j; break; } } } bool flag = false; for (int i = x + 1; i <= 8; i++) { if (m[i, y] == k * 10 + 5) { flag = true; break; } else if (m[i, y] != 0) break; } for (int i = x - 1; i >= 0; i--) { if (m[i, y] == k * 10 + 5) { flag = true; break; } else if (m[i, y] != 0) break; } for (int i = y + 1; i <= 9; i++) { if (m[x, i] == k * 10 + 5) { flag = true; break; } else if (m[x, i] != 0) break; } for (int i = y - 1; i >= 0; i--) { if (m[x, i] == k * 10 + 5) { flag = true; break; } else if (m[x, i] != 0) break; } if (flag) return flag; if (x <= 7 && m[x + 1, y] == k * 10 + 1) flag = true; if (y <= 8 && m[x, y + 1] == k * 10 + 1) flag = true; if (x >= 1 && m[x - 1, y] == k * 10 + 1) flag = true; if (y >= 1 && m[x, y - 1] == k * 10 + 1) flag = true; if (flag) return flag; if (x <= 7 && y <= 8 && m[x + 1, y + 1] == k * 10 + 2) flag = true; if (x >= 1 && y <= 8 && m[x - 1, y + 1] == k * 10 + 2) flag = true; if (x <= 7 && y >= 1 && m[x + 1, y - 1] == k * 10 + 2) flag = true; if (x >= 1 && y >= 1 && m[x - 1, y - 1] == k * 10 + 2) flag = true; if (flag) return flag; if (x <= 7 && m[x + 1, y] == k * 10 + 7) flag = true; if (y <= 8 && m[x, y + 1] == k * 10 + 7) flag = true; if (x >= 1 && m[x - 1, y] == k * 10 + 7) flag = true; if (y >= 1 && m[x, y - 1] == k * 10 + 7) flag = true; if (x <= 7 && y <= 8 && m[x + 1, y + 1] == k * 10 + 7) flag = true; if (x >= 1 && y <= 8 && m[x - 1, y + 1] == k * 10 + 7) flag = true; if (x <= 7 && y >= 1 && m[x + 1, y - 1] == k * 10 + 7) flag = true; if (x >= 1 && y >= 1 && m[x - 1, y - 1] == k * 10 + 7) flag = true; if (flag) return flag; if (x <= 6 && y <= 8 && m[x + 2, y + 1] == k * 10 + 4 && m[x + 1, y + 1] == 0) flag = true; if (x >= 2 && y <= 8 && m[x - 2, y + 1] == k * 10 + 4 && m[x - 1, y + 1] == 0) flag = true; if (x <= 6 && y >= 1 && m[x + 2, y - 1] == k * 10 + 4 && m[x + 1, y - 1] == 0) flag = true; if (x >= 2 && y >= 1 && m[x - 2, y - 1] == k * 10 + 4 && m[x - 1, y - 1] == 0) flag = true; if (x <= 7 && y <= 7 && m[x + 1, y + 2] == k * 10 + 4 && m[x + 1, y + 1] == 0) flag = true; if (x >= 1 && y <= 7 && m[x - 1, y + 2] == k * 10 + 4 && m[x - 1, y + 1] == 0) flag = true; if (x <= 7 && y >= 2 && m[x + 1, y - 2] == k * 10 + 4 && m[x + 1, y - 1] == 0) flag = true; if (x >= 1 && y >= 2 && m[x - 1, y - 2] == k * 10 + 4 && m[x - 1, y - 1] == 0) flag = true; if (flag) return flag; if (x <= 6 && y <= 7 && m[x + 2, y + 2] == k * 10 + 3 && m[x + 1, y + 1] == 0) flag = true; if (x >= 2 && y <= 7 && m[x - 2, y + 2] == k * 10 + 3 && m[x - 1, y + 1] == 0) flag = true; if (x <= 6 && y >= 2 && m[x + 2, y - 2] == k * 10 + 3 && m[x + 1, y - 1] == 0) flag = true; if (x >= 2 && y >= 2 && m[x - 2, y - 2] == k * 10 + 3 && m[x - 1, y - 1] == 0) flag = true; if (flag) return flag; if (x <= 5 && y <= 7 && m[x + 3, y + 2] == k * 10 + 6 && m[x + 2, y + 2] == 0 && m[x + 1, y + 1] == 0) flag = true; if (x >= 3 && y <= 7 && m[x - 3, y + 2] == k * 10 + 6 && m[x - 2, y + 2] == 0 && m[x - 1, y + 1] == 0) flag = true; if (x <= 5 && y >= 2 && m[x + 3, y - 2] == k * 10 + 6 && m[x + 2, y - 2] == 0 && m[x + 1, y - 1] == 0) flag = true; if (x >= 3 && y >= 2 && m[x - 3, y - 2] == k * 10 + 6 && m[x - 2, y - 2] == 0 && m[x - 1, y - 1] == 0) flag = true; if (x <= 6 && y <= 6 && m[x + 2, y + 3] == k * 10 + 6 && m[x + 2, y + 2] == 0 && m[x + 1, y + 1] == 0) flag = true; if (x >= 2 && y <= 6 && m[x - 2, y + 3] == k * 10 + 6 && m[x - 2, y + 2] == 0 && m[x - 1, y + 1] == 0) flag = true; if (x <= 6 && y >= 3 && m[x + 2, y - 3] == k * 10 + 6 && m[x + 2, y - 2] == 0 && m[x + 1, y - 1] == 0) flag = true; if (x >= 2 && y >= 3 && m[x - 2, y - 3] == k * 10 + 6 && m[x - 2, y - 2] == 0 && m[x - 1, y - 1] == 0) flag = true; return flag; } public void Write() { switch (m[tx, ty]) { case 1: { Console.Write("red captain;"); break; } case 2: { Console.Write("red guard;"); break; } case 3: { Console.Write("red elephant;"); break; } case 4: { Console.Write("red horse;"); break; } case 5: { Console.Write("red car;"); break; } case 6: { Console.Write("red duck;"); break; } case 7: { Console.Write("red soldier;"); break; } case 11: { Console.Write("blue captain;"); break; } case 12: { Console.Write("blue guard;"); break; } case 13: { Console.Write("blue elephant;"); break; } case 14: { Console.Write("blue horse;"); break; } case 15: { Console.Write("blue car;"); break; } case 16: { Console.Write("blue duck;"); break; } case 17: { Console.Write("blue soldier;"); break; } } switch (knockOut) { case 0: { Console.Write("NA;"); break; } case 1: { Console.Write("red captain;"); break; } case 2: { Console.Write("red guard;"); break; } case 3: { Console.Write("red elephant;"); break; } case 4: { Console.Write("red horse;"); break; } case 5: { Console.Write("red car;"); break; } case 6: { Console.Write("red duck;"); break; } case 7: { Console.Write("red soldier;"); break; } case 11: { Console.Write("blue captain;"); break; } case 12: { Console.Write("blue guard;"); break; } case 13: { Console.Write("blue elephant;"); break; } case 14: { Console.Write("blue horse;"); break; } case 15: { Console.Write("blue car;"); break; } case 16: { Console.Write("blue duck;"); break; } case 17: { Console.Write("blue soldier;"); break; } } if (knockOut == 1 || knockOut == 11) isCaptured = true; if (!isCaptured && isCheckmate) Console.Write("yes;"); else Console.Write("no;"); if (isCaptured) Console.WriteLine("yes"); else Console.WriteLine("no"); } } class MainClass { static public int Read() { int x = 0; int c = Console.Read(); while (c < '0' || c > '9') c = Console.Read(); while (c >= '0' && c <= '9') { x = (x * 10) + (c - 48); c = Console.Read(); } return x; } public static void Main(string[] args) { Map map = new Map(); map.Init(); int Q = Read(); for (int i = 1; i <= Q; i++) { map.Clear(); map.sy = Read(); map.sx = Read(); map.ty = Read(); map.tx = Read(); if (map.isCaptured) { Console.WriteLine("Invalid command"); continue; } map.CheckOut(); map.Move(); if (map.isInvalid) continue; map.isCheckmate = map.CheckMate(0) || map.CheckMate(1); map.Write(); map.side ^= 1; } } } }

__EOF__

本文作者Kaiser Wilheim
本文链接https://www.cnblogs.com/kaiserwilheim/p/16482066.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   南陽劉子驥  阅读(44)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示