#includeiostream#includestring#includecmathusingnamespacestd;enumTResult{//结局状态WHITEWIN=1,//白方赢BLACKWIN,//黑方赢STALEMATE,//僵局DRAW,//和局DEAD,//过多的输入PUZZLE,//无法决定移动棋子ILLEGAL//非法};constcharRESULT[8][20]={//结局状态输出表示,WhiteWin,BlackWin,Stalemate,Draw,DeadMoves,PuzzleMove,IllegalMove};enumTPieceType{//棋子类型SPACE=0,PAWN,//兵KING,//王QUEEN,//后ROOK,//车BISHOP,//象KNIGHT//马};enumTSide{NONE=0,WHITE,//黑方BLACK//白方};typedefstruct{//棋盘每个位置的表示TSideside;//所属玩家TPieceTypept;//棋子类型}TPiece;constintBOARDSIZE=8;//棋盘大小typedefTPieceTBoard[BOARDSIZE][BOARDSIZE];//棋盘intn;//棋谱步数TResultresult;//最后结局/**用来进行王车易位的布尔变量**whitecastled:白方是否已经王车易位*blackcastled:黑方是否已经王车易位*white0rookMoved:白方号位的车是否已经移动*white7rookMoved:白方号位的车是否已经移动*black0rookMoved:黑方号位的车是否已经移动*black7rookMoved:黑方号位的车是否已经移动*whitekingMoved:白方王是否已经移动*blackkingMoved:黑方王是否已经移动**/boolwhitecastled,blackcastled,white0rookMoved,white7rookMoved,black0rookMoved,black7rookMoved,whitekingMoved,blackkingMoved;TPieceTypeChessType(conststring&move){switch(move[0]){case'K'://王returnKING;case'Q'://后returnQUEEN;case'R'://车returnROOK;case'B'://象returnBISHOP;case'N'://马returnKNIGHT;}returnPAWN;//兵}TSideOpponent(TSideside){//获取对手类型if(side==WHITE)returnBLACK;returnWHITE;}voidclear(TBoardb,intx,inty){//清空棋盘b的(x,y)位置b[x][y].side=NONE;//所属玩家b[x][y].pt=SPACE;//棋子类型}voidinit(TBoardb){//初始化棋盘inti,j;//清空整个棋盘for(i=0;iBOARDSIZE;++i)for(j=0;jBOARDSIZE;++j){clear(b,i,j);}//摆放各个棋子for(i=0;iBOARDSIZE;++i){//棋盘前两行是白方b[0][i].side=WHITE;b[1][i].side=WHITE;b[1][i].pt=PAWN;//上面第二行是白方的兵//棋盘最后两行是黑方b[6][i].side=BLACK;b[7][i].side=BLACK;b[6][i].pt=PAWN;//倒数第二行是黑方的兵}b[0][0].pt=b[0][7].pt=b[7][0].pt=b[7][7].pt=ROOK;//初始化车的位置b[0][1].pt=b[0][6].pt=b[7][1].pt=b[7][6].pt=KNIGHT;//初始化马的位置b[0][2].pt=b[0][5].pt=b[7][2].pt=b[7][5].pt=BISHOP;//初始化象的位置b[0][3].pt=b[7][3].pt=QUEEN;//初始化后的位置b[0][4].pt=b[7][4].pt=KING;//初始化王的位置//初始化王车易位使用的布尔变量whitecastled=false;blackcastled=false;white0rookMoved=false;white7rookMoved=false;black0rookMoved=false;black7rookMoved=false;whitekingMoved=false;blackkingMoved=false;}voidSkipInput(intk){//棋局已经结束,忽略剩余的输入inti;charmv[20];for(i=k;in;++i){scanf_s(%s,mv);}}voidGetPosition(conststring&move,int&x,int&y){//从输入的移动步骤中获取棋子的目标位置intk=0;if(move[0]'a')//首字母是大写字母k=1;x=move[k+1]-'1';//行y=move[k]-'a';//列}boolOutOfBoard(intx,inty){//棋子是否超出棋盘界限if(x0||y0){returntrue;}if(xBOARDSIZE||yBOARDSIZE){returntrue;}returnfalse;}boolCanMovePawn(TBoardb,intx,inty,intx2,inty2,intflag){//判断能否把兵从(x,y)移动到(x2,y2),当flag=1时,表示(x,y)直接移动到(x2,y2),flag为其他表示从(x,y)吃子到(x2,y2)if(flag==1){//直接移动,即兵直线前进一格if(y!=y2||b[x2][y2].side!=NONE){//y坐标不能改变,无法前进returnfalse;}if(b[x][y].side==WHITE){//下棋的是白方if(x==1){//白方的兵是第一次移动returnx2==2||(x2==3&&b[2][y].side==NONE);//第一次移动兵可以移动格或格}else{returnx2==x+1;//不是第一次移动,就只能向前移动格}}else{//下棋的是黑方if(x==6){//黑方的兵是第一次移动returnx2==5||(x2==4&&b[5][y].side==NONE);//第一次移动兵可以移动格或格}else{returnx2==x-1;//不是第一次移动,就只能向前移动格}}}else{//吃子判断,吃子时,x向前格,y坐标改变格if(b[x][y].side==WHITE){//要吃子的是白方return(x2==x+1&&abs(y2-y)==1);}else{//要吃子的是黑方return(x2==x-1&&abs(y2-y)==1);}}returnfalse;}boolCanMoveKing(TBoardb,intx,inty,intx2,inty2){//判断能否把王从(x,y)移动到(x2,y2)return(abs(x-x2)=1&&abs(y-y2)=1);}boolCanMoveRook(TBoardb,intx,inty,intx2,inty2){//判断能否把车从(x,y)移动到(x2,y2)intdx,dy,i,xx,yy;//判断移动是否是直线if(x!=x2&&y!=y2){returnfalse;}//直线方向增量if(x2x)dx=-1;elsedx=1;if(y2y)dy=-1;elsedy=1;//x方向上移动for(i=1;iabs(y-y2);++i){yy=y+i*dy;if(b[x][yy].side!=NONE){//中间有棋子阻挡returnfalse;}}//y方向上移动for(i=1;iabs(x-x2);++i){xx=x+i*dx;if(b[xx][y].side!=NONE){//中间有棋子阻挡returnfalse;}}returntrue;}boolCanMoveBishop(TBoardb,intx,inty,intx2,inty2){//判断能否把象从(x,y)移动到(x2,y2)intdx,dy,i,xx,yy;//是否斜向移动if(abs(x-x2)!=abs(y-y2)){returnfalse;}//直线方向增量if(x2x)dx=-1;elsedx=1;if(y2y)dy=-1;elsedy=1;for(i=1;iabs(x-x2);++i){xx=x+i*dx;yy=y+i*dy;if(b[xx][yy].side!=NONE){//中间有棋子阻挡returnfalse;}}returntrue;}boolCanMoveQueen(TBoardb,intx,inty,intx2,inty2){//判断能否把王从(x,y)移动到(x2,y2)returnCanMoveRook(b,x,y,x2,y2)||CanMoveBishop(b,x,y,x2,y2);//王后等于车+象}boolCanMoveKnight(intx,inty,intx2,inty2){//判断马能否从(x,y)移动到(x2,y2)intxx,yy;xx=abs(x-x2);yy=abs(y-y2);return(xx+yy==3&&(xx==1||yy==1));//马行日,x或者y这两者之一移动格,另一方向移动格}boolCanMove(TBoardb,intx,inty,intx2,inty2,intflag){//判断一个棋子能否从(x,y)移动到(x2,y2),当flag=1时,直接移动,flag=2时,表示把(x2,y2)处的棋子给吃掉//判断是否越界if(OutOfBoard(x,y)||OutOfBoard(x2,y2)){returnfalse;}//判断原位置是否有棋子if(b[x][y].side==NONE){returnfalse;}//根据原来位置上棋子的不同类型判断是否合法switch(b[x][y].pt){casePAWN://兵returnCanMovePawn(b,x,y,x2,y2,flag);caseKING://王returnCanMoveKing(b,x,y,x2,y2);caseQUEEN://后returnCanMoveQueen(b,x,y,x2,y2);caseROOK://车returnCanMoveRook(b,x,y,x2,y2);caseBISHOP://象returnCanMoveBishop(b,x,y,x2,y2);caseKNIGHT://马returnCanMoveKnight(x,y,x2,y2);}returnfalse;}voidGetSourcePosition(TBoardb,intx2,inty2,int&x,int&y,TPieceTypect,TSideside){/*从给出的位置(x2,y2),类型ct和玩家side,求出移动的棋子的原来位置(x,y),,*当x=-2时,表示有重复移动方案(Puzzle),x=-1时表示没有移动可能(illegal)*/inti,j,flag=1;if(b[x2][y2].side!=NONE)//目标位置是对手的棋子,则此步为吃子方案flag=2;for(i=0;iBOARDSIZE;++i){for(j=0;jBOARDSIZE;++j){if(b[i][j].side==side&&b[i][j].pt==ct){//原位置合法并且是同一个子if(CanMove(b,i,j,x2,y2,flag)