【刘汝佳书】习题4-1 UVA1589

【2019.3.30】
读题二十分钟,写了一个小时,debug了四十分钟,郁闷

思路:
让黑将分别往左、下、右、上四个方向试探:
用checkSafe函数检查黑将在新位置是否安全,如果安全,checkSafe返回true,不安全则返回false
如果四个方向上都不安全,证明红已经把黑将死,输出YES,否则输出NO

checkSafe函数的流程:
1、首先调用checkGeneral查看原位置是否与红帅相对,如果是,证明安全,返回true(因为此时黑将可以一步吃掉红帅)
2、再次调用checkBeyondBound查看新位置是否越界,如果越界,证明不安全,返回false
3、调用checkGeneral查看新位置是否与红帅相对,如果相对,证明这个新位置不安全,返回false
4、调用checkChariot查看新位置是否会被车打,如果会,返回false
5、调用checkCannon查看新位置是否会被炮打,如果会,返回false
6、调用checkHorse查看新位置是否会被马打,如果会,返回false
7、返回true,新位置经检查很安全

值得注意的地方:
1、一定要首先查看原位置是否与红帅相对
2、注意连环炮现象

#include <iostream>

using namespace std;

char board[11][10];  //10*9 board

bool checkSafe(int bx, int by, int d);  //检查是否安全

bool checkBeyondBound(int x, int y);//检查黑将越界
bool checkGeneral(int x, int y);    //检查帅将相对
bool checkChariot(int x, int y);    //检查车
bool checkCannon(int x, int y);     //检查炮
bool checkHorse(int x, int y);      //检查马

bool checkHorseBound(int hx, int hy);   //检查马是否越界
bool isHorse(int hx, int hy);           //检查是否是马
bool isEmpty(int hobx, int hoby);       //检查马腿是否为空


int main()
{
    //freopen("C:\\Users\\Summer\\Desktop\\input.txt", "r", stdin);
    //freopen("C:\\Users\\Summer\\Desktop\\output.txt", "w", stdout);

    int N, bx, by;
    char c;
    int rx, ry;
    while(cin>>N>>bx>>by && N) {
        //初始化
        for(int i=0; i<11; i++)
            for(int j=0; j<10; j++)
                board[i][j]=' ';

        //输入棋盘
        while(N--) {
            cin>>c;
            cin>>rx>>ry;
            board[rx][ry]=c;
        }

        //检查黑将向四个方向走一步
        //是否会出现安全状态
        bool isCheckmate = true;
        for(int d=0; d<4; d++) {
            if(checkSafe(bx, by, d)) {
                isCheckmate = false;
                break;
            }
        }

        //如果没出现安全状态,证明将死,输出YES
        if(isCheckmate) cout<<"YES"<<endl;
        else            cout<<"NO"<<endl;
    }
    return 0;
}

//计算黑将的新位置
int movestep[4][2] =
{
    0, -1,  //左
    +1, 0,  //下
    0, +1,  //右
    -1, 0   //上
};

bool checkSafe(int bx, int by, int d)
{
    int nx = bx + movestep[d][0];
    int ny = by + movestep[d][1];
    //cout<<"direction:"<<d<<endl;

    if(checkGeneral(bx, by)) return true;
    //else cout<<"checkGeneral OK"<<endl;

    if(checkBeyondBound(nx, ny))   return false;
    //else cout<<"checkBound OK"<<endl;

    if(checkGeneral(nx, ny)) return false;
    //else cout<<"checkGeneral OK"<<endl;

    if(checkChariot(nx, ny)) return false;
    //else cout<<"checkChariot OK"<<endl;

    if(checkCannon(nx, ny))  return false;
    //else cout<<"checkCannon OK"<<endl;

    if(checkHorse(nx, ny))   return false;
    //else cout<<"checkHorse OK"<<endl;

    return true;
}

bool checkBeyondBound(int x, int y)
{
    return !(x>=1 && x<=3 && y>=4 && y<=6);
}

//检查同列是否与帅相对(从x往下找)
bool checkGeneral(int x, int y)
{
    for(int i=x+1; i<=10; i++) {
        if(board[i][y]==' ')      continue;
        else if(board[i][y]=='G') return true;
        else break;
    }
    return false;
}

//检查同行同列是否有车相对(从x开始往四方找)
bool checkChariot(int x, int y)
{
    for(int i=x+1; i<=10; i++) {
        if(board[i][y]==' ')      continue;
        else if(board[i][y]=='R') return true;
        else break;
    }
    for(int i=x-1; i>=1; i--) {
        if(board[i][y]==' ')      continue;
        else if(board[i][y]=='R') return true;
        else break;
    }
    for(int j=y+1; j<=9; j++) {
        if(board[x][j]==' ')      continue;
        else if(board[x][j]=='R') return true;
        else break;
    }
    for(int j=y-1; j>=0; j--) {
        if(board[x][j]==' ')      continue;
        else if(board[x][j]=='R') return true;
        else break;
    }
    return false;
}

//检查同行同列是否与炮相隔一个棋子
bool checkCannon(int x, int y)
{
    int cnt=0;  //相隔数目
    for(int i=x+1; i<=10; i++) {
        if(board[i][y]==' ')      continue;
        else if(cnt==1 && board[i][y]=='C') return true;
        else cnt++;
    }
    cnt=0;
    for(int i=x-1; i>=1; i--) {
        if(board[i][y]==' ') continue;
        else if(cnt==1 && board[i][y]=='C') return true;
        else cnt++;
    }
    cnt=0;
    for(int j=y+1; j<=9; j++) {
        if(board[x][j]==' ') continue;
        else if(cnt==1 && board[x][j]=='C') return true;
        else cnt++;
    }
    cnt=0;
    for(int j=y-1; j>=0; j--) {
        if(board[x][j]==' ') continue;
        else if(cnt==1 && board[x][j]=='C') return true;
        else cnt++;
    }
    return false;
}

//计算马有可能出现的位置
int horseLoca[8][2] =
{
    -2, +1, //右上
    -2, -1, //左上
    -1, -2, //左上
    +1, -2, //左下
    +2, -1, //左下
    +2, +1, //右下
    +1, +2, //右下
    -1, +2  //右上
};

//计算马腿位置
int hobLoca[8][2] =
{
    -1, +1,
    -1, -1,
    -1, -1,
    +1, -1,
    +1, -1,
    +1, +1,
    +1, +1,
    -1, +1
};

//检查八个方向的马和蹩马腿位置
bool checkHorse(int x, int y)
{
    int hx, hy;
    int hobx, hoby;
    for(int i=0; i<8; i++) {
        hx = x + horseLoca[i][0];
        hy = y + horseLoca[i][1];
        hobx = x + hobLoca[i][0];
        hoby = y + hobLoca[i][1];

        if(!checkHorseBound(hx, hy)) continue;
        if(isHorse(hx, hy) && isEmpty(hobx, hoby)) return true;
        //else cout<<"checkHorse OK:"<<hx<<' '<<hy<<' '<<isHorse(hx, hy)<<' '<<hobx<<' '<<hoby<<' '<<isEmpty(hobx,hoby)<<endl;
    }
    return false;
}

bool checkHorseBound(int hx, int hy)
{
    return (hx>=1 && hx<=10 && hy>=1 && hy<=9);
}

bool isHorse(int hx, int hy)
{
    return (board[hx][hy]=='H');
}

bool isEmpty(int hobx, int hoby)
{
    return (board[hobx][hoby]==' ');
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值