习题4-1象棋uva1589简单题解

第一次写博客,感觉有必要记录一下学习过程。就拿这题开刀了。

  1. 题目要求:给定一个棋盘残局,黑棋只有帅,红方只有帅和车马炮,且红方已将军,判断是否将死。
  2. 一开始理解错了,原本以为是判断红方能否最终取胜,瞬间感觉好难,仔细看才发现原来只是判断初始的这一将军是否把黑棋将死了。
  3. 有两个注意点(也坑了我好久),一是黑棋可能会吃子,二是初始的局面就有可能是两帅相对的情况,此时要判定为红棋没有将死,输出“NO”。
  4. 有两种思路:一是给红方每个子标记可攻击范围,在棋盘数组上设置标记,然后让黑帅移动,如果存在一个没有标记的地方且与黑帅位置相邻,则没有将死。我觉的这个思路有点麻烦,有很多不必要的操作。所以用了第二种思路:写一个子函数,给其一个坐标参数(x,y),判断黑帅是否可以移动到(x,y),然后再把黑帅的上下左右四个位置全判断一下,只要有一个可以即可判定为没有将死。
  5. 为了便于阅读,分别实现:位置(x,y)是否被炮威胁、是否被车威胁、是否被马威胁、是否与红帅相对的四个子函数。另外,单独增加一个子函数来计算同一条直线上两个坐标之间隔着多少个棋子,不在同一条直线上返回 -1。
  6. 还有一点就是对于任何一个棋子,它都保护不了自己所在的位置。犹如一个医生能够给别人做手术,但却给自己做不了手术。

以下是代码。

#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;
 }


  • 7
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值