第一次写博客,感觉有必要记录一下学习过程。就拿这题开刀了。
- 题目要求:给定一个棋盘残局,黑棋只有帅,红方只有帅和车马炮,且红方已将军,判断是否将死。
- 一开始理解错了,原本以为是判断红方能否最终取胜,瞬间感觉好难,仔细看才发现原来只是判断初始的这一将军是否把黑棋将死了。
- 有两个注意点(也坑了我好久),一是黑棋可能会吃子,二是初始的局面就有可能是两帅相对的情况,此时要判定为红棋没有将死,输出“NO”。
- 有两种思路:一是给红方每个子标记可攻击范围,在棋盘数组上设置标记,然后让黑帅移动,如果存在一个没有标记的地方且与黑帅位置相邻,则没有将死。我觉的这个思路有点麻烦,有很多不必要的操作。所以用了第二种思路:写一个子函数,给其一个坐标参数(x,y),判断黑帅是否可以移动到(x,y),然后再把黑帅的上下左右四个位置全判断一下,只要有一个可以即可判定为没有将死。
- 为了便于阅读,分别实现:位置(x,y)是否被炮威胁、是否被车威胁、是否被马威胁、是否与红帅相对的四个子函数。另外,单独增加一个子函数来计算同一条直线上两个坐标之间隔着多少个棋子,不在同一条直线上返回 -1。
- 还有一点就是对于任何一个棋子,它都保护不了自己所在的位置。犹如一个医生能够给别人做手术,但却给自己做不了手术。
以下是代码。
#include <bits/stdc++.h>
using namespace std;
char board[11][10];//车 R 马 H 炮 C 将帅 G
int rx, ry; //红方帅坐标
int chessPieces(int x1, int y1, int x2, int y2) {
int cnt = 0;
if(x1 == x2) {
if(y1 > y2)
swap(y1, y2);
for(int i = y1 + 1; i < y2; i++) {
if(board[x1][i] != 0)
cnt++;
}
} else if(y1 == y2) {
if(x1 > x2)
swap(x1, x2);
for(int i = x1 + 1; i < x2; i++) {
if(board[i][y1] != 0)
cnt++;
}
} else
cnt = -1;
return cnt;
}
//炮判断
bool checkCannon(int x, int y) {
for(int i = 1; i <= 9; i++) {
if(board[x][i] == 'C' && chessPieces(x, i, x, y) == 1)
return true;
}
for(int i = 1; i <= 10; i++) {
if(board[i][y] == 'C' && chessPieces(i, y, x, y) == 1)
return true;
}
return false;
}
//车判断
bool checkChariot(int x, int y) {
for(int i = 1; i <= 9; i++) {
if(i == y)
continue;
if(board[x][i] == 'R' && chessPieces(x, i, x, y) == 0)
return true;
}
for(int i = 1; i <= 10; i++) {
if(i == x)
continue;
if(board[i][y] == 'R' && chessPieces(i, y, x, y) == 0)
return true;
}
return false;
}
// 马判断
bool checkHorse(int x, int y) {
if(x == 3 && ((board[1][y - 1] == 'H' && board[2][y - 1] == 0) || (board[1][y + 1] == 'H' && board[2][y + 1] == 0)))
return true;
if((board[x - 1][y - 2] == 'H' && board[x - 1][y - 1] == 0) || (board[x - 1][y + 2] == 'H' && board[x - 1][y + 1] == 0))
return true;
if(board[x + 1][y - 1] == 0 && (board[x + 1][y - 2] == 'H' || board[x + 2][y - 1] == 'H'))
return true;
if(board[x + 1][y + 1] == 0 && (board[x + 1][y + 2] == 'H' || board[x + 2][y + 1] == 'H'))
return true;
return false;
}
//检查(x,y)是否对帅
bool checkGeneral(int x, int y) {
return y == ry && chessPieces(x, y, rx, ry) == 0;
}
bool canMoveTo(int x, int y) {
if(x < 1 || x > 3 || y < 4 || y > 6)
return false;
if(checkGeneral(x, y) || checkChariot(x, y) || checkHorse(x, y) || checkCannon(x, y))
return false;
return true;
}
int main() {
int n, x, y, a, b;
while(cin >> n >> x >> y, n != 0) {
memset(board, 0, sizeof(board));
for(int i = 0; i < n; i++) {
char ch;
cin >> ch >> a >> b;
board[a][b] = ch;
if(ch == 'G')
rx = a, ry = b;
}
if(checkGeneral(x, y))
cout << "NO\n";
else
cout << (canMoveTo(x - 1, y) || canMoveTo(x + 1, y) || canMoveTo(x, y - 1) || canMoveTo(x, y + 1) ? "NO\n" : "YES\n");
}
return 0;
}