题意:
给出象棋棋盘是10*9的矩阵,每个棋子在交点上,模拟红色棋子是否对黑色棋子将军了。
先输入n,表示将要输入红色棋子的数量,再输入x,y分别比表示黑色将棋子的横纵坐标。
然后n行,ch表示红色棋子的种类,x,y表示这个棋子的坐标。
如果将军:就是黑色棋子的将无论怎么移动都会被红色棋子吃掉。
输入保证棋子的当前状态是合法的且有黑色棋子恰好能够被红色棋子吃掉。
红色棋子的种类
H:表示马,每个马有8中走法,但是要考虑蹩马腿的情况
R:表示车,车可以沿着水平,竖直方向移动。
C:表示炮,炮吃掉棋子需要这个棋子和炮之间有一个棋子。
G:表示红色的帅,黑色的将不能和红色的帅见面,否则就算黑色的棋子输
(注意:这里的将,帅不考虑沿对角线移动)
思路:
建立两个棋盘,一个表示残局棋盘,另外一个表示红色棋子可以到达的地方,然后判读黑色棋子的下一步移动是否
能够到达一个合法的而且红色棋子吃不到的地方,如果可以到达,就不是将军局面,否则将军局面成立。
采用自顶向下的方式来模拟,先写好main函数,和需要用到的函数,然后在分别写每个函数。
main函数:先将所有棋子放到棋盘上,构建一个残局,同时存储每个红色棋子的种类和位置(这里可以采用结构体的方式
但是我参考大佬的文章后觉得二维数组更加优秀),然后再寻找每个红色棋子能够到达的位置。
(1)函数H寻找马能够到达的位置,枚举每个节点,判断是否有蹩马腿的情况,如果没有且位置合法就可以到达。
(2)函数C寻找炮能够到达的位置,先找到炮的架子,然后在去寻找所有炮能够达到的地方。
(3)函数RG寻找车,红色帅能够到达的位置,因为车和帅都有如果它们和其他棋子在同一条直线上就回吃掉另一个棋子的
性质,所以可以将它们写成一个函数。
优化:
(1)寻找所有x在[1,3]区间,y在[4,6]区间内红色棋子能够到达的位置。
(2)注意,黑色将在移动时只能上下左右4个方向,不能沿对角线移动(前几次考虑这个就错了)。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int c1[20][20],c2[20][20],op[20][20];
void H(int x,int y) //马达到的位置
{
if(c2[x+1][y]==0&&x+2<=10&&y-1>=1) c1[x+2][y-1]=1;
if(c2[x+1][y]==0&&x+2<=10&&y+1<=9) c1[x+2][y+1]=1;
if(c2[x-1][y]==0&&x-2>=1&&y-1>=1) c1[x-2][y-1]=1;
if(c2[x-1][y]==0&&x-2>=1&&y+1<=9) c1[x-2][y+1]=1;
if(c2[x][y-1]==0&&y-2>=1&&x-1>=1) c1[x-1][y-2]=1;
if(c2[x][y-1]==0&&y-2>=1&&x+1<=10) c1[x+1][y-2]=1;
if(c2[x][y+1]==0&&y+2<=9&&x-1>=1) c1[x-1][y+2]=1;
if(c2[x][y+1]==0&&y+2<=9&&x+1<=10) c1[x+1][y+2]=1;
}
void C(int x,int y)
{
if(x==1&&y>=4&&y<=6) //炮在x为1的情况下能够达到的合法位置
if(c2[2][y]!=1&&c2[2][y]!=0) c1[3][y]=1;
int i;
for(i=x-1;i>=1;i--){ //找炮上面的位置
if(c2[i][y]==1) return ;
if(c2[i][y]!=0) break;
}
for(i--;i>=1;i--){
c1[i][y]=1;
if(c2[i][y]!=0&&c2[i][y]!=1) break;
}
for(i=y+1;i<=9;i++){ //找炮右面的位置
if(c2[x][i]==1) return ;
if(c2[x][i]!=0) break;
}
for(i++;i<=9;i++){
c1[x][i]=1;
if(c2[x][i]!=0&&c2[x][i]!=1) break;
}
for(i=y-1;i>=1;i--){ //找炮左边的位置
if(c2[x][i]==1) return ;
if(c2[x][i]!=0) break;
}
for(i--;i>=1;i--){
c1[x][i]=1;
if(c2[x][i]!=0&&c2[x][i]!=1) break;
}
}
void RG(int x,int y) //将和帅能够到达的位置
{
int i;
for(i=x+1;i<=3;i++){
c1[i][y]=1;
if(c2[i][y]!=1&&c2[i][y]!=0) break;
}
for(i=x-1;i>=1;i--){
c1[i][y]=1;
if(c2[i][y]!=1&&c2[i][y]!=0) break;
}
for(i=y+1;i<=9;i++){
c1[x][i]=1;
if(c2[x][i]!=1&&c2[x][i]!=0) break;
}
for(i=y-1;i>=1;i--){
c1[x][i]=1;
if(c2[x][i]!=1&&c2[x][i]!=0) break;
}
}
bool pd(int x,int y) //判断,移动四个方向
{
bool fg=true;
if(x+1<=3&&c1[x+1][y]!=1) fg=false;
if(x-1>=1&&c1[x-1][y]!=1) fg=false;
if(y+1<=6&&c1[x][y+1]!=1) fg=false;
if(y-1>=4&&c1[x][y-1]!=1) fg=false;
return fg;
}
void Print()
{
int i,j;
for(i=1;i<=10;i++){
for(j=1;j<=9;j++) printf("%d ",c1[i][j]);
printf("\n");
}
printf("\n");
}
int main(void)
{
char ch[10];
int n,x,y,sx,sy,i;
while(~scanf("%d%d%d",&n,&sx,&sy)&&(n+sx+sy)){
memset(c1,0,sizeof(c1)); //禁止到达
memset(c2,0,sizeof(c2)); //残局
memset(op,0,sizeof(op));
c2[sx][sy]=1;
for(i=0;i<n;i++){
scanf("%s%d%d",ch,&x,&y);
c2[x][y]=ch[0]-'A';
op[i][0]=x;op[i][1]=y;
}
for(i=0;i<n;i++){
x=op[i][0];y=op[i][1];
char cc=(char)(c2[x][y]+'A');
if(cc=='G'||cc=='R') RG(x,y);
else if(cc=='C') C(x,y);
else if(cc=='H') H(x,y);
}
//Print();//调试代码
if(pd(sx,sy)==true) printf("YES\n");
else printf("NO\n");
}
return 0;
}