UVA 1589 Xiangqi (模拟)

1.可能当前状态是胜利的(直接飞将吃掉对面帅)
2.如果不是胜利的,检查四个方向,如果能移动的方向都是死,说明现在是必输状态
3.模拟各种死亡的条件,马,飞将,炮,车

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
char g[11][10];
int bx,by;//黑将的位置
int r = 10;
int c = 9;
int GM[4][2] = {{-1,0},{0,1},{1,0},{0,-1}};//将的移动方向
int HD[8][2] = {{-2,-1},{-2,1},{-1,2},{1,2},{2,1},{2,-1},{1,-2},{-1,-2}};//马相对于将的位置
int MJ[8][2] = {{-1,-1},{-1,1},{-1,1},{1,1},{1,1},{1,-1},{1,-1},{-1,-1}};//马脚相对于将的位置
bool isOut(int x,int y){//黑将是否出界
    return !(x>=1&&x<=3&&y>=4&&y<=6);
}
bool isOut2(int x,int y){//马是否出界
    return !(x>=1&&x<=r&&y>=1&&y<=c);
}
bool checkHorizontalFirst(int x,int y,char target){//横向是否能第一次遇见target
    int j;
    for(j=y-1;j>=1;j--)
        if(g[x][j])
            if(g[x][j]==target) return true;
            else break;
    for(j=y+1;j<=c;j++)
        if(g[x][j])
            if(g[x][j]==target) return true;
            else break;
    return false;
}
bool checkVerticalFirst(int x,int y,char target){//纵向是否能第一次遇见target
    int i;
    if(target!='G'){
        for(i=x-1;i>=1;i--)
            if(g[i][y])
                if(g[i][y]==target) return true;
                else break;
    }
    //如果检查飞将只需要向下查找就可以了
    for(i=x+1;i<=r;i++)
        if(g[i][y])
            if(g[i][y]==target) return true;
            else break;
    return false;
}
bool check1(int x,int y){//检查当前移动位置能否遇见车是否能遇见车
    return checkHorizontalFirst(x,y,'R')||checkVerticalFirst(x,y,'R');
}
bool check2(int x,int y){ //有没有飞将
    return checkVerticalFirst(x,y,'G');
}
bool check3(int x,int y){ //横纵向是否有炮
    int cnt;
    int i,j;
    int t ;
    int i1,j1;
    for(i=1;i<=r;i++){//纵向
        if(i!=x&&g[i][y]=='C'){
            int a = x;
            int b = i;
            if(a>b){
                t = a;
                a = b;
                b = t;
            }
            cnt = 0;//检查炮和将中间有多少子
            for(i1 = a+1;i1<=b-1;i1++){
                if(g[i1][y]){
                    cnt++;
                }
            }
            if(cnt==1) return true;
        }
    }
    for(j=1;j<=c;j++){
        if(j!=y&&g[x][j]=='C'){
                int a = y;
                int b = j;
                if(a>b){
                    t = a;
                    a = b;
                    b = t;
                }
                cnt = 0;//检查炮和将中间有多少子
                for(j1 = a+1;j1<=b-1;j1++){
                    if(g[x][j1]){
                        cnt++;
                    }
                }
                if(cnt==1) return true;
        }
    }
    return false;
}
bool check4(int x,int y){
    int i;
    for(i=0;i<8;i++){
        int nx = x + HD[i][0];
        int ny = y + HD[i][1];
        int nxx = x + MJ[i][0];
        int nyy = y + MJ[i][1];
        if(!isOut2(nx,ny)&&g[nx][ny]=='H'&&!g[nxx][nyy]){//这个位置没有出界,并且有马,而且没有别马脚
            return true;
        }
    }
    return false;
}
bool check(int x,int y){
    int cnt = 0;
    int dir = 0;
    int i;
    if(check2(x,y)) return false;//如果直接就能飞将杀死对面也就不需要检查死亡了。。。
    for(i=0;i<4;i++){
        int nx = x+GM[i][0];
        int ny = y+GM[i][1];
        if(!isOut(nx,ny)){
            dir++;
            //当前移动方向上有东西,吃掉
            char t = g[nx][ny];
            g[nx][ny] = '\0';
            if(check1(nx,ny)||check2(nx,ny)||check3(nx,ny)||check4(nx,ny)) cnt++;
            g[nx][ny] = t;//恢复图的状态
        }
    }
    return dir==cnt;
}
int main()
{
    int rnum,i,cx,cy;
    char cc;
    while(cin>>rnum>>bx>>by&&(rnum+bx+by)){
        memset(g,0,sizeof(g));
        for(i=0;i<rnum;i++){
            cin>>cc>>cx>>cy;
            g[cx][cy] = cc;
        }
        bool flag = check(bx,by);
        if(flag) cout<<"YES"<<endl;
        else cout<<"NO"<<endl;
    }
    return 0;
}

 

posted @ 2019-06-14 13:48  fanyuheng  阅读(82)  评论(0)    收藏  举报