国际象棋C.docx
- 文档编号:24784023
- 上传时间:2023-06-01
- 格式:DOCX
- 页数:30
- 大小:19.75KB
国际象棋C.docx
《国际象棋C.docx》由会员分享,可在线阅读,更多相关《国际象棋C.docx(30页珍藏版)》请在冰豆网上搜索。
国际象棋C
#include
#include
#include
usingnamespacestd;
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;i for(j=0;j { clear(b,i,j); } //摆放各个棋子 for(i=0;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;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(x<0||y<0) { returntrue; } if(x>BOARDSIZE||y>BOARDSIZE) { 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(x2 dx=-1; else dx=1; if(y2 dy=-1; else dy=1; //x方向上移动 for(i=1;i { yy=y+i*dy; if(b[x][yy].side! =NONE) {//中间有棋子阻挡 returnfalse; } } //y方向上移动 for(i=1;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(x2 dx=-1; else dx=1; if(y2 dy=-1; else dy=1; for(i=1;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;i { for(j=0;j { if(b[i][j].side==side&&b[i][j].pt==ct) {//原位置合法并且是同一个子 if(CanMove(b,i,j,x2,y2,flag)) { if(x==-1) {//能够移动并且不重复,找到原来棋子的位置 x=i; y=j; } else {//能够移动并且有方案,说明有重复 x=-2; return; } } } } } } voidMarkRookMove(TSideside,intx,inty) { if(side==WHITE) { if(x==0) { if(y==0) { white0rookMoved=true;//白方号车已经移动 } if(y==7) { white7rookMoved=true;//白方号车已经移动 } } return; } if(x==7) { if(y==0) { black0rookMoved=true;//黑方号车已经移动 } if(y==7) { black7rookMoved=true;//黑方号车已经移动 } } } voidChessMove(TBoardb,intx,inty,intx2,inty2) {//棋子从(x,y)移动到(x2,y2) b[x2][y2].side=b[x][y].side; b[x2][y2].pt=b[x][y].pt; clear(b,x,y);//清空原位置 } voidMakeMove(TBoardb,conststring&move,TSideside) {//根据输入的步骤mv,玩家side移动棋子 intx,y,x2,y2; GetPosition(move,x2,y2);//目标位置 if(b[x2][y2].side==side) {//目标位置处已经有我方的棋子了,此步非法 result=ILLEGAL; return; } x=-1; GetSourcePosition(b,x2,y2,x,y,ChessType(move),side);//尝试寻找原位置 if(x==-1) {//非法状态 result=ILLEGAL; return; } elseif(x==-2) {//重复状态 result=PUZZLE; return; } //移动的棋子是车时,设置王车易位布尔变量 if(b[x][y].pt==ROOK) { MarkRookMove(side,x,y); } //移动的棋子是王时,设置王车易位布尔变量 if(b[x][y].pt==KING) { if(side==WHITE)//白方王移动了 whitekingMoved=true; else//黑方王移动了 blackkingMoved=true; } ChessMove(b,x,y,x2,y2);//移动棋子 } boolGridBeAttack(TBoardb,intx,inty,TSidebyWho) {//判断位置(x,y)的棋子能否被吃掉 inti,j; for(i=0;i { for(j=0;j { if(b[i][j].side==byWho&&CanMove(b,i,j,x,y,2)) {//会被对手吃掉的 returntrue; } } } returnfalse; } boolCanCastle(TBoardb,TSideside,intflag) {//判断是否能够进行王车易位 introw,i; if(side==WHITE) {//白方王车易位 if(whitekingMoved==true) {//王已经动了,不能王车易位 returnfalse; } if(flag==3&&white7rookMoved==true) {//目标车已经动了,不能王车易位 returnfalse; } if(flag==5&&white0rookMoved==true) {//目标车已经动了,不能王车易位 returnfalse; } } else {//黑方王车易位 if(blackkingMoved==true) {//王已经动了 returnfalse; } if(flag==3&&black7rookMoved==true) {//目标车已经动了,不能王车易位 returnfalse; } if(flag==5&&black0rookMoved==true) {//目标车已经动了,不能王车易位 returnfalse; } } if(side==WHITE) row=0; else row=7; if(flag==5) { for(i=1;i<4;++i) { if(b[row][i].side! =NONE) {//王车之间是否有棋子,若有则不能易位 returnfalse; } } for(i=0;i<5;++i) { if(GridBeAttack(b,row,i,Opponent(side))==true) {//在目标位置上会被对手吃掉,不能王车易位 returnfalse; } } } else { for(i=5;i { if(b[row][i].side! =NONE) {//王车之间是否有棋子,若有则不能易位 returnfalse; } } for(i=4;i { if(GridBeAttack(b,row,i,Opponent(side))) {//在目标位置上会被对手吃掉,不能王车易位 returnfalse; } } } returntrue;//检查符合要求,可以王车易位 } voidCastle(TBoardb,TSideside,intflag) {//进行王车易位,flag=3,表示靠近王的车King-sidecastle,flag=5时,表示Queen-sidecastle introw; if(side==WHITE) { if(whitecastled==true) {//白方是否已经易位,已经易过位,不能再易了 result=ILLEGAL; return; } else whitecastled=true;//设置易位变量 } else { if(blackcastled==true) {//黑方是否已经易位,已经易过位,不能再易了 result=ILLEGAL; return; } else blackcastled=true; } if(CanCastle(b,side,flag)==true) {//判断是否能够易位 if(side==WHITE) { row=0; } else { row=7; } if(flag==3) {//进行王车易位 ChessMove(b,row,4,row,6); ChessMove(b,row,7,row,5); } else { ChessMove(b,row,4,row,2); ChessMove(b,row,0,row,3); } } else {//无法王车易位,此步非法 result=ILLEGAL; } } voidGetKingPosition(TBoardb,TSideside,int&x,int&y) {//寻找国王的位置 inti,j; for(i=0;i { for(j=0;j { if(b[i][j].pt==KING&&b[i][j].side==side) {//找到指定方的王 x=i; y=j; return; } } }
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 国际象棋