题解 P5380 【[THUPC2019]鸭棋】
距离CSP还有10天整的时候,发现自己的算法能力已经崩溃了,百般无奈之下开刷黑模拟,于是在三天之后有了这篇题解
我们先整理一下题目大意:
1、这是一道模拟,模拟一种神奇的棋类游戏
2、棋盘和棋子题目已给出,记得多看几遍(其中鸭的移动方式更是需要好好理解)
3、输入是一堆操作,把(a,b)上的棋移到(c,d)上
4、输出分两种:不合法输出"Invalid command",合法则输出移动的棋,被吃的棋,是否形成将军,游戏是否结束
题意梳理完毕,那我们开始思索解决这道题的方法
1、用二维数组存储地图,用数字代替每一种棋(其实用字符也行,但比较麻烦)
- 我们大可以用1~7分别表示王,士,象,马,车,鸭,兵
- 因为有红蓝方,我们可以通过十位是否为1来判断是哪一方
2、移动步骤
- 看到好多大佬都像搜索那样存储移动,但我觉得太麻烦了,还不如在函数中判断当前棋子是哪一种,再直接枚举移动方式
3、判断将军
- 一开始我的想法是将移动函数和将军函数合成一个,因为他们都可以利用棋子的移动判断
(从而减少码量),但后来咕了所以拆成了两个
4、输出结果
- 输出结果其实不是很复杂,记录该次移动被吃的棋,最后输出就是了
一道模拟题本来没有什么难度,但是为什么也能排成黑题呢?
-
有些人说,模拟题考察代码能力啊! 我反对,因为代码能力指明白了算法后把它打出来,而不是单纯的暴力
(像我就只会暴力算法垃圾) -
有些人说,模拟题考察人的耐心啊!我半赞成,因为有的模拟题真的是打着打着就不想做了
-
那模拟题考察什么呢?
-
我认为啊,模拟题考察人的整理和逻辑 (蒟蒻观点大佬勿喷)
-
你要同时考虑很多的事情,比如这里需不需要特判,那里需不需要return,最后需不需要换行,中间是否要break等等
-
所以,我将以蒟蒻的亲身体验,指出本题容易掉坑的一些地方:
1、 每次移动的的时候记得将原来棋子所在的位置清零,并处理它要去的地方
2、注意处理红蓝关系的转换,以及棋盘的边界问题(被卡一次)
3、复制粘贴的时候记得进行彻底的修改,要不然这道题都打完了再去找非常痛苦(被卡三次,总计时间一天)
4、王被抓了以后判断游戏结束,但同时也要记录是哪个王被抓了(被卡一次)
5、每一次移动棋子的时候有很多的限制条件,其中马、象、鸭注意撇腿,车注意中间不能有子(马、鸭、车各被卡了一次)
6、这种大模拟一次写过很难,所以必定调试,注意有一些多余的不该出现的东西要删除(为此CE一次)
那我们开始分析代码吧:
inline void init() //初始化棋盘
{
mapp[0][4]=1,mapp[9][4]=11;
mapp[0][3]=2,mapp[0][5]=2,mapp[9][3]=12,mapp[9][5]=12;
mapp[0][2]=3,mapp[0][6]=3,mapp[9][2]=13,mapp[9][6]=13;
mapp[0][1]=4,mapp[0][7]=4,mapp[9][1]=14,mapp[9][7]=14;
mapp[0][0]=5,mapp[0][8]=5,mapp[9][0]=15,mapp[9][8]=15;
mapp[2][0]=6,mapp[2][8]=6,mapp[7][0]=16,mapp[7][8]=16;
mapp[3][0]=7,mapp[3][2]=7,mapp[3][4]=7,mapp[3][6]=7,mapp[3][8]=7;
mapp[6][0]=17,mapp[6][2]=17,mapp[6][4]=17,mapp[6][6]=17,mapp[6][8]=17;
}
主函数其实只需包含几个分函数
int main()
{
init();
scanf("%d",&Q);
for(register int i=1;i<=Q;i++)
{
scanf("%d%d%d%d",&a,&b,&c,&d); //读入
if(capture) {puts("Invalid command");continue;} //如果游戏已结束,那后续操作都不合法
initmove(); //初始化移动
move(); //移动
if(flagout) continue; //如果移动中不合法则继续(输出在函数中判断)
check(); //检查是否将军
print();
if(turn==0) turn=1; //转换红蓝方
else turn=0;
}
return 0;
}
初始化:
inline void initmove() // 初始化 move()
{
gai=0;
flagout=0;
extra=0;
capture=0;
jiang=0;
}
移动
- 关于移动,我打了一张大大的表
- 在把表放出来之前,先说明几个define
#define out {flagout=1;puts("Invalid command");return;}
#define bounce (a>=0&&a<=9&&b>=0&&b<=8&&c>=0&&c<=9&&d>=0&&d<=8)
其中out是如果输入不合法,标记,输出,返回
bounce是确保起点终点都在边界之内
if(turn==1) extra=10; //因为我用十位来判断红蓝方,所以蓝方则加十
-
我们需要判断棋子的落点的子
-
举个例子,如果落点没有子,那当然可以走
-
如果红棋的落点为蓝棋,那也可以走
-
但红棋落点为红棋就不能走
-
所以:
bool fang(bool turn) // 是哪一方在动 & bounce
{
if(turn==0) return (mapp[c][d]==0||mapp[c][d]>10);
else return (mapp[c][d]==0||mapp[c][d]<10);
}
- 棋子落地之后我们要判断有无棋子被吃:
void lose(int c,int d) //判断吞兵
{
if(mapp[c][d]==1) capture=1,gai=1; //王被吃了标记
else if(mapp[c][d]==11) capture=2,gai=11;
else if(mapp[c][d]>10) gai=mapp[c][d],lan--; //标记被吃的棋
else if(mapp[c][d]>0) gai=mapp[c][d],hong--; //hong和lan用来计数,但发现其实没有什么用
}
- 最后我们要把棋子放过去
void exchange(int e,int extra)
{
mapp[a][b]=0,mapp[c][d]=e+extra;
which=e+extra;
}
该放表了
inline void move()
{
//条件 :符合该棋的移动 路上||终点无棋 终点敌方? 没越界
if(turn==1) extra=10;
if(mapp[a][b]==1+extra)
{
if(bounce==0) out //前面提到 边界
if(c-a==1&&b==d&&fang(turn)) {lose(c,d);exchange(1,extra);return;} //符合移动规则和移动方,则判断吃子和移动
if(a-c==1&&b==d&&fang(turn)) {lose(c,d);exchange(1,extra);return;}
if(a==c&&b-d==1&&fang(turn)) {lose(c,d);exchange(1,extra);return;}
if(a==c&&d-b==1&&fang(turn)) {lose(c,d);exchange(1,extra);return;}
out
}
if(mapp[a][b]==2+extra)
{
if(bounce==0) out
if(c-a==1&&b-d==1&&fang(turn)) {lose(c,d);exchange(2,extra);return;}
if(a-c==1&&b-d==1&&fang(turn)) {lose(c,d);exchange(2,extra);return;}
if(c-a==1&&d-b==1&&fang(turn)) {lose(c,d);exchange(2,extra);return;}
if(a-c==1&&d-b==1&&fang(turn)) {lose(c,d);exchange(2,extra);return;}
out
}
if(mapp[a][b]==3+extra)
{
if(bounce==0) out
if(c==a+2&&d==b+2&&fang(turn)&&mapp[a+1][b+1]==0) {lose(c,d);exchange(3,extra);return;}
if(c==a+2&&d==b-2&&fang(turn)&&mapp[a+1][b-1]==0) {lose(c,d);exchange(3,extra);return;}
if(c==a-2&&d==b+2&&fang(turn)&&mapp[a-1][b+1]==0) {lose(c,d);exchange(3,extra);return;}
if(c==a-2&&d==b-2&&fang(turn)&&mapp[a-1][b-1]==0) {lose(c,d);exchange(3,extra);return;}
out
}
if(mapp[a][b]==4+extra)
{
if(bounce==0) out
if(c-a==2&&d-b==1&&fang(turn)&&mapp[a+1][b]==0) {lose(c,d);exchange(4,extra);return;}
if(c-a==1&&d-b==2&&fang(turn)&&mapp[a][b+1]==0) {lose(c,d);exchange(4,extra);return;}
if(c-a==-1&&d-b==2&&fang(turn)&&mapp[a][b+1]==0) {lose(c,d);exchange(4,extra);return;}
if(c-a==-2&&d-b==1&&fang(turn)&&mapp[a-1][b]==0) {lose(c,d);exchange(4,extra);return;}
if(c-a==-2&&d-b==-1&&fang(turn)&&mapp[a-1][b]==0) {lose(c,d);exchange(4,extra);return;}
if(c-a==-1&&d-b==-2&&fang(turn)&&mapp[a][b-1]==0) {lose(c,d);exchange(4,extra);return;}
if(c-a==1&&d-b==-2&&fang(turn)&&mapp[a][b-1]==0) {lose(c,d);exchange(4,extra);return;}
if(c-a==2&&d-b==-1&&fang(turn)&&mapp[a+1][b]==0) {lose(c,d);exchange(4,extra);return;}
out
}
if(mapp[a][b]==5+extra)
{
if(bounce==0) out
if(a==c)
{
if(d>b)
{
for(register int i=b+1;i<d;i++) if(mapp[a][i]) out //有障碍
if(fang(turn)) {lose(c,d);exchange(5,extra);return;} //判断吃,更新
}
else if(d<b)
{
for(register int i=b-1;i>d;i--) if(mapp[a][i]) out
if(fang(turn)) {lose(c,d);exchange(5,extra);return;}
}
else out
}
else if(b==d)
{
if(c>a)
{
for(register int i=a+1;i<c;i++)
if(mapp[i][b]) out
if(fang(turn)) {lose(c,d);exchange(5,extra);return;}
}
else if(c<a)
{
for(register int i=a-1;i>c+1;i--)
if(mapp[i][b]) out
if(fang(turn)) {lose(c,d);exchange(5,extra);return;}
}
else out
}
else out
}
if(mapp[a][b]==6+extra) //这里一定要仔细。。。
{
if(bounce==0) out
if(c-a==2&&d-b==3&&fang(turn)&&mapp[a][b+1]==0&&mapp[a+1][b+2]==0) {lose(c,d);exchange(6,extra);return;}
if(c-a==3&&d-b==2&&fang(turn)&&mapp[a+1][b]==0&&mapp[a+2][b+1]==0) {lose(c,d);exchange(6,extra);return;}
if(c-a==-2&&d-b==3&&fang(turn)&&mapp[a][b+1]==0&&mapp[a-1][b+2]==0) {lose(c,d);exchange(6,extra);return;}
if(c-a==-3&&d-b==2&&fang(turn)&&mapp[a-1][b]==0&&mapp[a-2][b+1]==0) {lose(c,d);exchange(6,extra);return;}
if(c-a==2&&d-b==-3&&fang(turn)&&mapp[a][b-1]==0&&mapp[a+1][b-2]==0) {lose(c,d);exchange(6,extra);return;}
if(c-a==3&&d-b==-2&&fang(turn)&&mapp[a+1][b]==0&&mapp[a+2][b-1]==0) {lose(c,d);exchange(6,extra);return;}
if(c-a==-2&&d-b==-3&&fang(turn)&&mapp[a][b-1]==0&&mapp[a-1][b-2]==0) {lose(c,d);exchange(6,extra);return;}
if(c-a==-3&&d-b==-2&&fang(turn)&&mapp[a-1][b]==0&&mapp[a-2][b-1]==0) {lose(c,d);exchange(6,extra);return;}
out
}
if(mapp[a][b]==7+extra)
{
if(bounce==0) out
if(c-a==1&&b==d&&fang(turn)) {lose(c,d);exchange(7,extra);return;}
if(a-c==1&&b==d&&fang(turn)) {lose(c,d);exchange(7,extra);return;}
if(a==c&&b-d==1&&fang(turn)) {lose(c,d);exchange(7,extra);return;}
if(a==c&&d-b==1&&fang(turn)) {lose(c,d);exchange(7,extra);return;}
if(c-a==1&&b-d==1&&fang(turn)) {lose(c,d);exchange(7,extra);return;}
if(a-c==1&&b-d==1&&fang(turn)) {lose(c,d);exchange(7,extra);return;}
if(c-a==1&&d-b==1&&fang(turn)) {lose(c,d);exchange(7,extra);return;}
if(a-c==1&&d-b==1&&fang(turn)) {lose(c,d);exchange(7,extra);return;}
out
}
out
}
接下来是判断将军
-
其实我们发现,将军函数的代码和move中大部分重合
-
其实我们发现,将军函数本可以和move结合
-
但我就不
(原因是我这么写然后写挂了改了半个小时才改回来)
inline void check() // 检查将军
{
for(register int i=0;i<=9;i++)
{
for(register int j=0;j<=8;j++) //暴力枚举每一个点
{
if(mapp[i][j]==0) continue;
checkmate(i,j); //有棋则搜
if(jiang) return; //如果搜到了也就没必要继续了
}
}
}
- 再来一个define
#define checkok {jiang=1;return;} //符合将军条件则标记,返回
放表:
inline void checkmate(int p,int q)
{
if(mapp[p][q]>10) checkturn=1,checkextra=10; //checkturn是这颗棋的目标,checkextra和move中的extra同理
else checkturn=11,checkextra=0;
if(mapp[p][q]==1+checkextra)
{
if(mapp[p+1][q]==checkturn&&0<=p+1&&p+1<=9&&0<=q&&q<=8) checkok //一定要判断边界
if(mapp[p-1][q]==checkturn&&0<=p-1&&p-1<=9&&0<=q&&q<=8) checkok //虽然理论上不判断也可以
if(mapp[p][q+1]==checkturn&&0<=p&&p<=9&&0<=q+1&&q+1<=8) checkok //因为边界之外的棋不会有目标编号
if(mapp[p][q-1]==checkturn&&0<=p&&p<=9&&0<=q-1&&q-1<=8) checkok //但是我没判断就是死了,所以。。。
}
if(mapp[p][q]==2+checkextra)
{
if(mapp[p+1][q+1]==checkturn&&0<=p+1&&p+1<=9&&0<=q+1&&q+1<=8) checkok
if(mapp[p-1][q+1]==checkturn&&0<=p-1&&p-1<=9&&0<=q+1&&q+1<=8) checkok
if(mapp[p+1][q-1]==checkturn&&0<=p+1&&p+1<=9&&0<=q-1&&q-1<=8) checkok
if(mapp[p-1][q-1]==checkturn&&0<=p-1&&p-1<=9&&0<=q-1&&q-1<=8) checkok
}
if(mapp[p][q]==3+checkextra)
{
if(mapp[p+2][q+2]==checkturn&&mapp[p+1][q+1]==0&&0<=p+2&&p+2<=9&&0<=q+2&&q+2<=8) checkok
if(mapp[p-2][q+2]==checkturn&&mapp[p-1][q+1]==0&&0<=p-2&&p-2<=9&&0<=q+2&&q+2<=8) checkok
if(mapp[p+2][q-2]==checkturn&&mapp[p+1][q-1]==0&&0<=p+2&&p+2<=9&&0<=q-2&&q-2<=8) checkok
if(mapp[p-2][q-2]==checkturn&&mapp[p-1][q-1]==0&&0<=p-2&&p-2<=9&&0<=q-2&&q-2<=8) checkok
}
if(mapp[p][q]==4+checkextra)
{
if(mapp[p+1][q+2]==checkturn&&mapp[p][q+1]==0&&0<=p+1&&p+1<=9&&0<=q+2&&q+2<=8) checkok
if(mapp[p+2][q+1]==checkturn&&mapp[p+1][q]==0&&0<=p+2&&p+2<=9&&0<=q+1&&q+1<=8) checkok
if(mapp[p+2][q-1]==checkturn&&mapp[p+1][q]==0&&0<=p+2&&p+2<=9&&0<=q-1&&q-1<=8) checkok
if(mapp[p+1][q-2]==checkturn&&mapp[p][q-1]==0&&0<=p+1&&p+1<=9&&0<=q-2&&q-2<=8) checkok
if(mapp[p-1][q-2]==checkturn&&mapp[p][q-1]==0&&0<=p-1&&p-1<=9&&0<=q-2&&q-2<=8) checkok
if(mapp[p-2][q-1]==checkturn&&mapp[p-1][q]==0&&0<=p-2&&p-2<=9&&0<=q-1&&q-1<=8) checkok
if(mapp[p-2][q+1]==checkturn&&mapp[p-1][q]==0&&0<=p-2&&p-2<=9&&0<=q+1&&q+1<=8) checkok
if(mapp[p-1][q+2]==checkturn&&mapp[p][q+1]==0&&0<=p-1&&p-1<=9&&0<=q+2&&q+2<=8) checkok
}
if(mapp[p][q]==5+checkextra)
{
for(register int i=p+1;i<=9;i++)
{
if(mapp[i][q]==checkturn) checkok
if(mapp[i][q]!=0) return;
}
for(register int i=p-1;i>=0;i--)
{
if(mapp[i][q]==checkturn) checkok
if(mapp[i][q]!=0) return;
}
for(register int i=q+1;i<=8;i++)
{
if(mapp[p][i]==checkturn) checkok
if(mapp[p][i]!=0) return;
}
for(register int i=q-1;i>=0;i--)
{
if(mapp[p][i]==checkturn) checkok
if(mapp[p][i]!=0) return;
}
}
if(mapp[p][q]==6+checkextra)
{
if(mapp[p+2][q+3]==checkturn&&mapp[p][q+1]==0&&mapp[p+1][q+2]==0&&0<=p+2&&p+2<=9&&0<=q+3&&q+3<=8) checkok
if(mapp[p+3][q+2]==checkturn&&mapp[p+1][q]==0&&mapp[p+2][q+1]==0&&0<=p+3&&p+3<=9&&0<=q+2&&q+2<=8) checkok
if(mapp[p+3][q-2]==checkturn&&mapp[p+1][q]==0&&mapp[p+2][q-1]==0&&0<=p+3&&p+3<=9&&0<=q-2&&q-2<=8) checkok
if(mapp[p+2][q-3]==checkturn&&mapp[p][q-1]==0&&mapp[p+1][q-2]==0&&0<=p+2&&p+2<=9&&0<=q-3&&q-3<=8) checkok
if(mapp[p-2][q-3]==checkturn&&mapp[p][q-1]==0&&mapp[p-1][q-2]==0&&0<=p-2&&p-2<=9&&0<=q-3&&q-3<=8) checkok
if(mapp[p-3][q-2]==checkturn&&mapp[p-1][q]==0&&mapp[p-2][q-1]==0&&0<=p-3&&p-3<=9&&0<=q-2&&q-2<=8) checkok
if(mapp[p-3][q+2]==checkturn&&mapp[p-1][q]==0&&mapp[p-2][q+1]==0&&0<=p-3&&p-3<=9&&0<=q+2&&q+2<=8) checkok
if(mapp[p-2][q+3]==checkturn&&mapp[p][q+1]==0&&mapp[p-1][q+2]==0&&0<=p-2&&p-2<=9&&0<=q+3&&q+3<=8) checkok
}
if(mapp[p][q]==7+checkextra)
{
if(mapp[p+1][q]==checkturn&&0<=p+1&&p+1<=9&&0<=q&&q<=8) checkok
if(mapp[p-1][q]==checkturn&&0<=p-1&&p-1<=9&&0<=q&&q<=8) checkok
if(mapp[p][q+1]==checkturn&&0<=p&&p<=9&&0<=q+1&&q+1<=8) checkok
if(mapp[p][q-1]==checkturn&&0<=p&&p<=9&&0<=q-1&&q-1<=8) checkok
if(mapp[p+1][q+1]==checkturn&&0<=p+1&&p+1<=9&&0<=q+1&&q+1<=8) checkok
if(mapp[p-1][q+1]==checkturn&&0<=p-1&&p-1<=9&&0<=q+1&&q+1<=8) checkok
if(mapp[p+1][q-1]==checkturn&&0<=p+1&&p+1<=9&&0<=q-1&&q-1<=8) checkok
if(mapp[p-1][q-1]==checkturn&&0<=p-1&&p-1<=9&&0<=q-1&&q-1<=8) checkok
}
}
最后我们来输出
inline void print() //输出
{
if(mapp[c][d]==1) printf("red captain;"); //直接判终点的那颗棋
else if(mapp[c][d]==2) printf("red guard;"); //因为在起点的那颗被移过来了
else if(mapp[c][d]==3) printf("red elephant;");
else if(mapp[c][d]==4) printf("red horse;");
else if(mapp[c][d]==5) printf("red car;");
else if(mapp[c][d]==6) printf("red duck;");
else if(mapp[c][d]==7) printf("red soldier;");
else if(mapp[c][d]==11) printf("blue captain;");
else if(mapp[c][d]==12) printf("blue guard;");
else if(mapp[c][d]==13) printf("blue elephant;");
else if(mapp[c][d]==14) printf("blue horse;");
else if(mapp[c][d]==15) printf("blue car;");
else if(mapp[c][d]==16) printf("blue duck;");
else if(mapp[c][d]==17) printf("blue soldier;");
if(gai==1) printf("red captain;"); //gai记录被修改的
else if(gai==2) printf("red guard;");
else if(gai==3) printf("red elephant;");
else if(gai==4) printf("red horse;");
else if(gai==5) printf("red car;");
else if(gai==6) printf("red duck;");
else if(gai==7) printf("red soldier;");
else if(gai==11) printf("blue captain;");
else if(gai==12) printf("blue guard;");
else if(gai==13) printf("blue elephant;");
else if(gai==14) printf("blue horse;");
else if(gai==15) printf("blue car;");
else if(gai==16) printf("blue duck;");
else if(gai==17) printf("blue soldier;");
else printf("NA;"); //注意没有的话输出NA
if(capture==0&&jiang) printf("yes;");
else printf("no;");
if(capture) puts("yes"); //注意这里输出没有分号!!!
else puts("no");
}
于是我们愉快的A掉了这道题
放代码(我提交的时候的代码,内含我写这道题时自己放的注释):
//记得每次移动前加 lose(c,d)
//注意转换turn
//注意移动时清空之前的格子
//复制粘贴时记得进行必要修改
//注意棋盘的边界
//check时修改extra
//发现其实extra是turn的10倍,但是懒得改了
//记得captain被抓了也要标记修改了哪颗棋
//记得动车的时候fang()
#include <bits/stdc++.h>
//#include <windows.h> //////////////
using namespace std;
#define out {flagout=1;puts("Invalid command");return;}
#define bounce (a>=0&&a<=9&&b>=0&&b<=8&&c>=0&&c<=9&&d>=0&&d<=8)
#define checkok {jiang=1;return;} //////////
int Q;
int a,b,c,d;
// 全局变量区
int mapp[12][12]; //列 行 : 如 mapp[4][3]表红方第二个兵
bool turn=0; // 红0 蓝1 //王1 士2 象3 马4 车5 鸭6 兵7 红单位,蓝双位
int checkturn; //记录check的时候对方的王
int hong=16,lan=16,gai; //总兵数 被吃兵
// 红蓝变量区
bool flagout; //判断是否被out掉
bool capture=0,jiang=0; // 1为被抓/将军
int extra,checkextra; // move的时候结果是什么兵的修改
int which; // move的时候调用的什么兵
//特殊辅助区
//int yhong=1,ylan=2,ybai=3;
//void Color(int a){
// if(a==1) SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY|FOREGROUND_RED);
// if(a==2) SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY|FOREGROUND_BLUE|FOREGROUND_GREEN);
// if(a==3) SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY|FOREGROUND_GREEN|FOREGROUND_BLUE|FOREGROUND_RED);
//}
inline void init() //初始化棋盘
{
mapp[0][4]=1,mapp[9][4]=11;
mapp[0][3]=2,mapp[0][5]=2,mapp[9][3]=12,mapp[9][5]=12;
mapp[0][2]=3,mapp[0][6]=3,mapp[9][2]=13,mapp[9][6]=13;
mapp[0][1]=4,mapp[0][7]=4,mapp[9][1]=14,mapp[9][7]=14;
mapp[0][0]=5,mapp[0][8]=5,mapp[9][0]=15,mapp[9][8]=15;
mapp[2][0]=6,mapp[2][8]=6,mapp[7][0]=16,mapp[7][8]=16;
mapp[3][0]=7,mapp[3][2]=7,mapp[3][4]=7,mapp[3][6]=7,mapp[3][8]=7;
mapp[6][0]=17,mapp[6][2]=17,mapp[6][4]=17,mapp[6][6]=17,mapp[6][8]=17;
}
void lose(int c,int d) //判断吞兵
{
if(mapp[c][d]==1) capture=1,gai=1;
else if(mapp[c][d]==11) capture=2,gai=11;
else if(mapp[c][d]>10) gai=mapp[c][d],lan--;
else if(mapp[c][d]>0) gai=mapp[c][d],hong--;
}
bool fang(bool turn) // 是哪一方在动 & bounce
{
if(turn==0) return (mapp[c][d]==0||mapp[c][d]>10);
else return (mapp[c][d]==0||mapp[c][d]<10);
}
void exchange(int e,int extra)
{
mapp[a][b]=0,mapp[c][d]=e+extra;
which=e+extra;
}
inline void move()
{
//条件 :符合该棋的移动 路上||终点无棋 终点敌方? 没越界
if(turn==1) extra=10;
if(mapp[a][b]==1+extra)
{
if(bounce==0) out
if(c-a==1&&b==d&&fang(turn)) {lose(c,d);exchange(1,extra);return;}
if(a-c==1&&b==d&&fang(turn)) {lose(c,d);exchange(1,extra);return;}
if(a==c&&b-d==1&&fang(turn)) {lose(c,d);exchange(1,extra);return;}
if(a==c&&d-b==1&&fang(turn)) {lose(c,d);exchange(1,extra);return;}
out
}
if(mapp[a][b]==2+extra)
{
if(bounce==0) out
if(c-a==1&&b-d==1&&fang(turn)) {lose(c,d);exchange(2,extra);return;}
if(a-c==1&&b-d==1&&fang(turn)) {lose(c,d);exchange(2,extra);return;}
if(c-a==1&&d-b==1&&fang(turn)) {lose(c,d);exchange(2,extra);return;}
if(a-c==1&&d-b==1&&fang(turn)) {lose(c,d);exchange(2,extra);return;}
out
}
if(mapp[a][b]==3+extra)
{
if(bounce==0) out
if(c==a+2&&d==b+2&&fang(turn)&&mapp[a+1][b+1]==0) {lose(c,d);exchange(3,extra);return;}
if(c==a+2&&d==b-2&&fang(turn)&&mapp[a+1][b-1]==0) {lose(c,d);exchange(3,extra);return;}
if(c==a-2&&d==b+2&&fang(turn)&&mapp[a-1][b+1]==0) {lose(c,d);exchange(3,extra);return;}
if(c==a-2&&d==b-2&&fang(turn)&&mapp[a-1][b-1]==0) {lose(c,d);exchange(3,extra);return;}
out
}
if(mapp[a][b]==4+extra)
{
if(bounce==0) out
if(c-a==2&&d-b==1&&fang(turn)&&mapp[a+1][b]==0) {lose(c,d);exchange(4,extra);return;}
if(c-a==1&&d-b==2&&fang(turn)&&mapp[a][b+1]==0) {lose(c,d);exchange(4,extra);return;}
if(c-a==-1&&d-b==2&&fang(turn)&&mapp[a][b+1]==0) {lose(c,d);exchange(4,extra);return;}
if(c-a==-2&&d-b==1&&fang(turn)&&mapp[a-1][b]==0) {lose(c,d);exchange(4,extra);return;}
if(c-a==-2&&d-b==-1&&fang(turn)&&mapp[a-1][b]==0) {lose(c,d);exchange(4,extra);return;}
if(c-a==-1&&d-b==-2&&fang(turn)&&mapp[a][b-1]==0) {lose(c,d);exchange(4,extra);return;}
if(c-a==1&&d-b==-2&&fang(turn)&&mapp[a][b-1]==0) {lose(c,d);exchange(4,extra);return;}
if(c-a==2&&d-b==-1&&fang(turn)&&mapp[a+1][b]==0) {lose(c,d);exchange(4,extra);return;}
out
}
if(mapp[a][b]==5+extra)
{
if(bounce==0) out
if(a==c)
{
if(d>b)
{
for(register int i=b+1;i<d;i++) if(mapp[a][i]) out //有障碍
if(fang(turn)) {lose(c,d);exchange(5,extra);return;} //判断吃,更新
}
else if(d<b)
{
for(register int i=b-1;i>d;i--) if(mapp[a][i]) out
if(fang(turn)) {lose(c,d);exchange(5,extra);return;}
}
else out
}
else if(b==d)
{
if(c>a)
{
for(register int i=a+1;i<c;i++)
if(mapp[i][b]) out
if(fang(turn)) {lose(c,d);exchange(5,extra);return;}
}
else if(c<a)
{
for(register int i=a-1;i>c+1;i--)
if(mapp[i][b]) out
if(fang(turn)) {lose(c,d);exchange(5,extra);return;}
}
else out
}
else out
}
if(mapp[a][b]==6+extra)
{
if(bounce==0) out
if(c-a==2&&d-b==3&&fang(turn)&&mapp[a][b+1]==0&&mapp[a+1][b+2]==0) {lose(c,d);exchange(6,extra);return;}
if(c-a==3&&d-b==2&&fang(turn)&&mapp[a+1][b]==0&&mapp[a+2][b+1]==0) {lose(c,d);exchange(6,extra);return;}
if(c-a==-2&&d-b==3&&fang(turn)&&mapp[a][b+1]==0&&mapp[a-1][b+2]==0) {lose(c,d);exchange(6,extra);return;}
if(c-a==-3&&d-b==2&&fang(turn)&&mapp[a-1][b]==0&&mapp[a-2][b+1]==0) {lose(c,d);exchange(6,extra);return;}
if(c-a==2&&d-b==-3&&fang(turn)&&mapp[a][b-1]==0&&mapp[a+1][b-2]==0) {lose(c,d);exchange(6,extra);return;}
if(c-a==3&&d-b==-2&&fang(turn)&&mapp[a+1][b]==0&&mapp[a+2][b-1]==0) {lose(c,d);exchange(6,extra);return;}
if(c-a==-2&&d-b==-3&&fang(turn)&&mapp[a][b-1]==0&&mapp[a-1][b-2]==0) {lose(c,d);exchange(6,extra);return;}
if(c-a==-3&&d-b==-2&&fang(turn)&&mapp[a-1][b]==0&&mapp[a-2][b-1]==0) {lose(c,d);exchange(6,extra);return;}
out
}
if(mapp[a][b]==7+extra)
{
if(bounce==0) out
if(c-a==1&&b==d&&fang(turn)) {lose(c,d);exchange(7,extra);return;}
if(a-c==1&&b==d&&fang(turn)) {lose(c,d);exchange(7,extra);return;}
if(a==c&&b-d==1&&fang(turn)) {lose(c,d);exchange(7,extra);return;}
if(a==c&&d-b==1&&fang(turn)) {lose(c,d);exchange(7,extra);return;}
if(c-a==1&&b-d==1&&fang(turn)) {lose(c,d);exchange(7,extra);return;}
if(a-c==1&&b-d==1&&fang(turn)) {lose(c,d);exchange(7,extra);return;}
if(c-a==1&&d-b==1&&fang(turn)) {lose(c,d);exchange(7,extra);return;}
if(a-c==1&&d-b==1&&fang(turn)) {lose(c,d);exchange(7,extra);return;}
out
}
out
}
inline void initmove() // 初始化 move()
{
gai=0;
flagout=0;
extra=0;
capture=0;
jiang=0;
}
inline void checkmate(int p,int q)
{
if(mapp[p][q]>10) checkturn=1,checkextra=10;
else checkturn=11,checkextra=0;
if(mapp[p][q]==1+checkextra)
{
if(mapp[p+1][q]==checkturn&&0<=p+1&&p+1<=9&&0<=q&&q<=8) checkok
if(mapp[p-1][q]==checkturn&&0<=p-1&&p-1<=9&&0<=q&&q<=8) checkok
if(mapp[p][q+1]==checkturn&&0<=p&&p<=9&&0<=q+1&&q+1<=8) checkok
if(mapp[p][q-1]==checkturn&&0<=p&&p<=9&&0<=q-1&&q-1<=8) checkok
}
if(mapp[p][q]==2+checkextra)
{
if(mapp[p+1][q+1]==checkturn&&0<=p+1&&p+1<=9&&0<=q+1&&q+1<=8) checkok
if(mapp[p-1][q+1]==checkturn&&0<=p-1&&p-1<=9&&0<=q+1&&q+1<=8) checkok
if(mapp[p+1][q-1]==checkturn&&0<=p+1&&p+1<=9&&0<=q-1&&q-1<=8) checkok
if(mapp[p-1][q-1]==checkturn&&0<=p-1&&p-1<=9&&0<=q-1&&q-1<=8) checkok
}
if(mapp[p][q]==3+checkextra)
{
if(mapp[p+2][q+2]==checkturn&&mapp[p+1][q+1]==0&&0<=p+2&&p+2<=9&&0<=q+2&&q+2<=8) checkok
if(mapp[p-2][q+2]==checkturn&&mapp[p-1][q+1]==0&&0<=p-2&&p-2<=9&&0<=q+2&&q+2<=8) checkok
if(mapp[p+2][q-2]==checkturn&&mapp[p+1][q-1]==0&&0<=p+2&&p+2<=9&&0<=q-2&&q-2<=8) checkok
if(mapp[p-2][q-2]==checkturn&&mapp[p-1][q-1]==0&&0<=p-2&&p-2<=9&&0<=q-2&&q-2<=8) checkok
}
if(mapp[p][q]==4+checkextra)
{
if(mapp[p+1][q+2]==checkturn&&mapp[p][q+1]==0&&0<=p+1&&p+1<=9&&0<=q+2&&q+2<=8) checkok
if(mapp[p+2][q+1]==checkturn&&mapp[p+1][q]==0&&0<=p+2&&p+2<=9&&0<=q+1&&q+1<=8) checkok
if(mapp[p+2][q-1]==checkturn&&mapp[p+1][q]==0&&0<=p+2&&p+2<=9&&0<=q-1&&q-1<=8) checkok
if(mapp[p+1][q-2]==checkturn&&mapp[p][q-1]==0&&0<=p+1&&p+1<=9&&0<=q-2&&q-2<=8) checkok
if(mapp[p-1][q-2]==checkturn&&mapp[p][q-1]==0&&0<=p-1&&p-1<=9&&0<=q-2&&q-2<=8) checkok
if(mapp[p-2][q-1]==checkturn&&mapp[p-1][q]==0&&0<=p-2&&p-2<=9&&0<=q-1&&q-1<=8) checkok
if(mapp[p-2][q+1]==checkturn&&mapp[p-1][q]==0&&0<=p-2&&p-2<=9&&0<=q+1&&q+1<=8) checkok
if(mapp[p-1][q+2]==checkturn&&mapp[p][q+1]==0&&0<=p-1&&p-1<=9&&0<=q+2&&q+2<=8) checkok
}
if(mapp[p][q]==5+checkextra)
{
for(register int i=p+1;i<=9;i++)
{
if(mapp[i][q]==checkturn) checkok
if(mapp[i][q]!=0) return;
}
for(register int i=p-1;i>=0;i--)
{
if(mapp[i][q]==checkturn) checkok
if(mapp[i][q]!=0) return;
}
for(register int i=q+1;i<=8;i++)
{
if(mapp[p][i]==checkturn) checkok
if(mapp[p][i]!=0) return;
}
for(register int i=q-1;i>=0;i--)
{
if(mapp[p][i]==checkturn) checkok
if(mapp[p][i]!=0) return;
}
}
if(mapp[p][q]==6+checkextra)
{
if(mapp[p+2][q+3]==checkturn&&mapp[p][q+1]==0&&mapp[p+1][q+2]==0&&0<=p+2&&p+2<=9&&0<=q+3&&q+3<=8) checkok
if(mapp[p+3][q+2]==checkturn&&mapp[p+1][q]==0&&mapp[p+2][q+1]==0&&0<=p+3&&p+3<=9&&0<=q+2&&q+2<=8) checkok
if(mapp[p+3][q-2]==checkturn&&mapp[p+1][q]==0&&mapp[p+2][q-1]==0&&0<=p+3&&p+3<=9&&0<=q-2&&q-2<=8) checkok
if(mapp[p+2][q-3]==checkturn&&mapp[p][q-1]==0&&mapp[p+1][q-2]==0&&0<=p+2&&p+2<=9&&0<=q-3&&q-3<=8) checkok
if(mapp[p-2][q-3]==checkturn&&mapp[p][q-1]==0&&mapp[p-1][q-2]==0&&0<=p-2&&p-2<=9&&0<=q-3&&q-3<=8) checkok
if(mapp[p-3][q-2]==checkturn&&mapp[p-1][q]==0&&mapp[p-2][q-1]==0&&0<=p-3&&p-3<=9&&0<=q-2&&q-2<=8) checkok
if(mapp[p-3][q+2]==checkturn&&mapp[p-1][q]==0&&mapp[p-2][q+1]==0&&0<=p-3&&p-3<=9&&0<=q+2&&q+2<=8) checkok
if(mapp[p-2][q+3]==checkturn&&mapp[p][q+1]==0&&mapp[p-1][q+2]==0&&0<=p-2&&p-2<=9&&0<=q+3&&q+3<=8) checkok
}
if(mapp[p][q]==7+checkextra)
{
if(mapp[p+1][q]==checkturn&&0<=p+1&&p+1<=9&&0<=q&&q<=8) checkok
if(mapp[p-1][q]==checkturn&&0<=p-1&&p-1<=9&&0<=q&&q<=8) checkok
if(mapp[p][q+1]==checkturn&&0<=p&&p<=9&&0<=q+1&&q+1<=8) checkok
if(mapp[p][q-1]==checkturn&&0<=p&&p<=9&&0<=q-1&&q-1<=8) checkok
if(mapp[p+1][q+1]==checkturn&&0<=p+1&&p+1<=9&&0<=q+1&&q+1<=8) checkok
if(mapp[p-1][q+1]==checkturn&&0<=p-1&&p-1<=9&&0<=q+1&&q+1<=8) checkok
if(mapp[p+1][q-1]==checkturn&&0<=p+1&&p+1<=9&&0<=q-1&&q-1<=8) checkok
if(mapp[p-1][q-1]==checkturn&&0<=p-1&&p-1<=9&&0<=q-1&&q-1<=8) checkok
}
}
inline void check() // 检查将军
{
for(register int i=0;i<=9;i++)
{
for(register int j=0;j<=8;j++)
{
if(mapp[i][j]==0) continue;
checkmate(i,j);
if(jiang) return;
}
}
}
inline void print() //输出
{
if(mapp[c][d]==1) printf("red captain;");
else if(mapp[c][d]==2) printf("red guard;");
else if(mapp[c][d]==3) printf("red elephant;");
else if(mapp[c][d]==4) printf("red horse;");
else if(mapp[c][d]==5) printf("red car;");
else if(mapp[c][d]==6) printf("red duck;");
else if(mapp[c][d]==7) printf("red soldier;");
else if(mapp[c][d]==11) printf("blue captain;");
else if(mapp[c][d]==12) printf("blue guard;");
else if(mapp[c][d]==13) printf("blue elephant;");
else if(mapp[c][d]==14) printf("blue horse;");
else if(mapp[c][d]==15) printf("blue car;");
else if(mapp[c][d]==16) printf("blue duck;");
else if(mapp[c][d]==17) printf("blue soldier;");
if(gai==1) printf("red captain;");
else if(gai==2) printf("red guard;");
else if(gai==3) printf("red elephant;");
else if(gai==4) printf("red horse;");
else if(gai==5) printf("red car;");
else if(gai==6) printf("red duck;");
else if(gai==7) printf("red soldier;");
else if(gai==11) printf("blue captain;");
else if(gai==12) printf("blue guard;");
else if(gai==13) printf("blue elephant;");
else if(gai==14) printf("blue horse;");
else if(gai==15) printf("blue car;");
else if(gai==16) printf("blue duck;");
else if(gai==17) printf("blue soldier;");
else printf("NA;");
if(capture==0&&jiang) printf("yes;");
else printf("no;");
if(capture) puts("yes");
else puts("no");
}
int main()
{
// freopen("2test.in","r",stdin);
// freopen("test.out","w",stdout);
init();
// Color(ybai); /////
// int cc=0;
// for(register int i=9;i>=0;i--)
// {
// for(register int j=8;j>=0;j--)
// {
// cout<<setw(5)<<mapp[i][j];
// }
// puts("");
// }
scanf("%d",&Q);
for(register int i=1;i<=Q;i++)
{
// cout<<i<<" "; ////
scanf("%d%d%d%d",&a,&b,&c,&d);
if(capture) {puts("Invalid command");continue;}
initmove();
move();
if(flagout) continue;
// if(i<=586)
// system("cls"); /////
// for(register int i=9;i>=0;i--)
// {
// for(register int j=0;j<=8;j++)
// {
// if(mapp[i][j]<10&&mapp[i][j]!=0)
// {
// Color(yhong),cout<<setw(5)<<mapp[i][j],Color(ybai);
// }
// else if(mapp[i][j]>10)
// {
// Color(ylan),cout<<setw(5)<<mapp[i][j],Color(ybai);
// }
// else Color(ybai),cout<<setw(5)<<mapp[i][j];
// }
// puts("");
// }
// puts(""),puts(""); /////
check();
print();
if(turn==0) turn=1;
else turn=0;
// if(i>=590) system("pause");
// if(i>=357)
}
return 0;
}
写题解不易,兹磁一下呗!