题目
题解
大框架
首先构建函数的大框架——这个问题要怎么解决呢?
可选项:
- 分析帝宫九个位置可否放置将或帅,储存在二位数组Room里(0为不可放置,1为可放置)。判断将或帅一步内可移动的位置在Room中的值是否为1。
- 将所有棋子置于容器中,判断每一个将或帅可移动的位置循环一次容器,确认是否被将军。
可行性分析:
- 可行,帝宫九个位置,需要一个3*3的数组即可,只用循环一次棋子和一次将帅的移动方式,时间上的复杂程度也不高。
- 可行,按规定是只有7个对方棋子,假设将帅位置在中间(最多的移动方式-4次),所需的计算量为28个函数运算,时间上复杂程度也没有超出。
例外情况
- 考虑对方飞将的可能性(中国象棋里其实不存在这种情况,博主分析时忽略了,在做Udebug才知道还有这种坑爹操作)
- 注意,你的棋子是可能被吃掉的,也就是说当炮、马、将军三者连在一起时,将军可以吃掉马摆脱被将死的局面。或者车在将的左右且同处于帝宫内,可能不构成将军。
构建函数
充分考虑各种情况后可以开始写各个棋子的函数了。再次之前,我们先定义一下头文件和全局变量。
#include <cstdio>
#include <cstring>
#include <math.h>
using namespace std;
#define f(i,m,n) for (int i = m; i<n; i++)
int B[11][10]= {0};
int M[5][2]= {0};
int RM[3][3];
int BGX=1,BGY=1,FC = 1;
struct Chess {
char ty;
int x,y;
};
- cstdio -> input ; cstring -> memset ; math.h -> cos/sin
- 一定要cstring,网上那个c++编译器不吃string这个头文件
- 经常调用的循环也定义一下,可以简洁很多
- B是Board的缩写,定义棋盘,方便车炮帅等函数的构造
- M是Move的缩写,定义黑方将军可移动位置,主要是防止红方棋子被吃和验证帝宫内位置是否可达到
- RM是Room的缩写,确定帝宫里哪些位置是可以达到的。
- FC是Face Check的缩写,防止飞将的异常情况
- 定义一个struct,main函数中可以生成一个struct的array,储存棋子。
函数“马”
可以先写“马”的函数,因为马即使被吃了,也不会有大的影响(马走日,若将能吃掉马,这一马必定攻击不到将)
void Horse (int x,int y){
int x1, y1;
f(m,1,5){f(n,0,2){
if(B[x1 = x+sin(m*M_PI/2)][y1 = y+cos(m*M_PI/2)] == 0){
x1= x + sqrt(5)*sin((22.5+(2*m-n)*45)*M_PI/180) + 0.5;
y1= y + sqrt(5)*cos((22.5+(2*m-n)*45)*M_PI/180) + 0.5;
if (3<x1 && x1<7 && 0<y1 && y1<4) RM[x1-4][y1-1] = 0;
}
}}
}
- 输入为马的 x,y 值
- if 那一行确认没有蹩马脚的情况
- 这里调用了数学函数,马行走的路线是1:2:√5, 每个角间隔为45°。
- sin 和 cos 都是弧度制,不知道为什么 /180一定要放在最后。
- 另外记得加0.5,所有的float -> int 都是使用了floor()函数。
#include <cstdio>
#include <string>
#include <math.h>
using namespace std;
#define f(i,m,n) for (int i = m; i<n; i++)
int B[11][10]= {0};
int M[5][2]= {0};
int RM[3][3];
int BGX=1,BGY=1,FC = 1;
struct Chess {
char ty;
int x,y;
};
int verify (int x,int y){
f(n,0,4){
if (M[n][0]==x&&M[n][1]==y){return 1;}
}
return 0;
}
void Ch (int x,int y,int L,int R,char ty){
int n = R==0?x:y, sum=0,bk=100;
if (n>L){
int c = L; L = n; n = c;
}
f(i,n+1,L){
if(R==0?B[i][y]:B[x][i]){
if(bk == 100)bk = i;
sum ++;
}
}
if (ty == 'C'?sum==1:sum==0){
if(ty != 'G'||x!=BGX){
f(i,0,3){
if (R==0){
if ((ty=='C'&&i==bk-4&&verify(bk,y))||(i==x-4&&verify(x,y))) continue;}
else{
if ((ty=='C'&&i==bk-1&&verify(x,bk))||(i==y-1&&verify(x,y))) continue;}
R==0?RM[i][y-1]=0:RM[x-4][i] = 0;
}}
else FC =0;
}
}
void Horse (int x,int y){
int x1, y1;
f(m,1,5){f(n,0,2){
if(B[x1 = x+sin(m*M_PI/2)][y1 = y+cos(m*M_PI/2)] == 0){
x1= x + sqrt(5)*sin((22.5+(2*m-n)*45)*M_PI/180) + 0.5;
y1= y + sqrt(5)*cos((22.5+(2*m-n)*45)*M_PI/180) + 0.5;
if (3<x1 && x1<7 && 0<y1 && y1<4) RM[x1-4][y1-1] = 0;
}
}}
}
void C (char ty, int x, int y){
int sum = 0;
if (y<4)Ch(x,y,BGX,0,ty);
if (3<x && x<7)Ch(x,y,BGY,1,ty);
}
int main (){
memset(RM,1,sizeof(RM));
int N,x,y;
Chess O[9];
while (scanf("%d%d%d\n",&N,&BGY,&BGX)==3&&N){
f(n,0,4){
x= BGX+sin(n*M_PI/2)+0.5;
y= BGY+cos(n*M_PI/2)+0.5;
if(3<x&&x<7&&0<y&&y<4){
M[n][0]=x;
M[n][1]=y;
}
}
f(i,0,N){
scanf("%c%d%d\n",&O[i].ty,&O[i].y,&O[i].x);
B[O[i].x][O[i].y] = 1;
}
f(i,0,N){
O[i].ty == 'H'?Horse(O[i].x,O[i].y):C(O[i].ty,O[i].x,O[i].y);
}
f(n,0,4){
if(M[n][0]){
if (!FC||RM[M[n][0]-4][M[n][1]-1]) {
printf("NO\n");
break;}
}
if (n==3) printf("YES\n");
}
memset(B,0,sizeof(B));
memset(M,0,sizeof(M));
memset(RM,1,sizeof(RM));
FC = 1;
}
return 0;
}