国际象棋C++Word文件下载.docx
《国际象棋C++Word文件下载.docx》由会员分享,可在线阅读,更多相关《国际象棋C++Word文件下载.docx(25页珍藏版)》请在冰豆网上搜索。
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;
Q'
//后
returnQUEEN;
R'
//车
returnROOK;
B'
//象
returnBISHOP;
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<
BOARDSIZE;
++i)
for(j=0;
j<
++j)
clear(b,i,j);
//摆放各个棋子
//棋盘前两行是白方
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;
n;
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]-'
//列
boolOutOfBoard(intx,inty)
{//棋子是否超出棋盘界限
if(x<
0||y<
0)
returntrue;
if(x>
BOARDSIZE||y>
BOARDSIZE)
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坐标不能改变,无法前进
if(b[x][y].side==WHITE)
{//下棋的是白方
if(x==1)
{//白方的兵是第一次移动
returnx2==2||(x2==3&
&
b[2][y].side==NONE);
//第一次移动兵可以移动格或格
else
returnx2==x+1;
//不是第一次移动,就只能向前移动格
{//下棋的是黑方
if(x==6)
{//黑方的兵是第一次移动
returnx2==5||(x2==4&
b[5][y].side==NONE);
returnx2==x-1;
{//吃子判断,吃子时,x向前格,y坐标改变格
{//要吃子的是白方
return(x2==x+1&
abs(y2-y)==1);
else
{//要吃子的是黑方
return(x2==x-1&
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)
//直线方向增量
if(x2<
x)
dx=-1;
dx=1;
if(y2<
dy=-1;
dy=1;
//x方向上移动
for(i=1;
abs(y-y2);
yy=y+i*dy;
if(b[x][yy].side!
{//中间有棋子阻挡
//y方向上移动
abs(x-x2);
xx=x+i*dx;
if(b[xx][y].side!
boolCanMoveBishop(TBoardb,intx,inty,intx2,inty2)
{//判断能否把象从(x,y)移动到(x2,y2)
//是否斜向移动
if(abs(x-x2)!
=abs(y-y2))
if(b[xx][yy].side!
boolCanMoveQueen(TBoardb,intx,inty,intx2,inty2)
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))
//判断原位置是否有棋子
if(b[x][y].side==NONE)
//根据原来位置上棋子的不同类型判断是否合法
switch(b[x][y].pt)
returnCanMovePawn(b,x,y,x2,y2,flag);
returnCanMoveKing(b,x,y,x2,y2);
returnCanMoveQueen(b,x,y,x2,y2);
returnCanMoveRook(b,x,y,x2,y2);
returnCanMoveBishop(b,x,y,x2,y2);
returnCanMoveKnight(x,y,x2,y2);
voidGetSourcePosition(TBoardb,intx2,inty2,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;
for(j=0;
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;
{//能够移动并且有方案,说明有重复
x=-2;
return;
voidMarkRookMove(TSideside,intx,inty)
if(x==0)
if(y==0)
white0rookMoved=true;
//白方号车已经移动
if(y==7)
white7rookMoved=true;
if(x==7)
black0rookMoved=true;
//黑方号车已经移动
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;
x=-1;
GetSourcePosition(b,x2,y2,x,y,ChessType(move),side);
//尝试寻找原位置
{//非法状态
elseif(x==-2)
{//重复状态
result=PUZZLE;
//移动的棋子是车时,设置王车易位布尔变量
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)的棋子能否被吃掉
if(b[i][j].side==byWho&
CanMove(b,i,j,x,y,2))
{//会被对手吃掉的
boolCanCastle(TBoardb,TSideside,intflag)
{//判断是否能够进行王车易位
introw,i;
{//白方王车易位
if(whitekingMoved==true)
{//王已经动了,不能王车易位
if(flag==3&
white7rookMoved==true)
{//目标车已经动了,不能王车易位
if(flag==5&
white0rookMoved==true)
{//黑方王车易位
if(blackkingMoved==true)
{//王已经动了
if(flag==3&
black7rookMoved==true)
if(flag==5&
black0rookMoved==true)
row=0;
row=7;
if(flag==5)
4;
if(b[row][i].side!
{//王车之间是否有棋子,若有则不能易位
5;
if(GridBeAttack(b,row,i,Opponent(side))==true)
{//在目标位置上会被对手吃掉,不能王车易位
for(i=5;
BOARDSIZE-1;
for(i=4;
if(GridBeAttack(b,row,i,Opponent(side)))
//检查符合要求,可以王车易位
voidCastle(TBoardb,TSideside,intflag)
{//进行王车易位,flag=3,表示靠近王的车King-sidecastle,flag=5时,表示Queen-sidecastle
introw;
if(whitecastled==true)
{//白方是否已经易位,已经易过位,不能再易了
return;
whitecastled=true;
//设置易位变量
if(blackcastled==true)
{//黑方是否已经易位,已经易过位,不能再易了
blackcastled=true;
if(CanCastle(b,side,flag)==true)
{//判断是否能够易位
if(flag==3)
{//进行王车易位
ChessMove(b,row,4,row,6);
ChessMove(b,row,7,row,5);
ChessMove(b,row,4,row,2);
ChessMove(b,row,0,row,3);
{//无法王车易位,此步非法
voidGetKingPosition(TBoardb,TSideside,int&
{//寻找国王的位置
if(b[i][j].pt==KING&
b[i][j].side==side)
{//找到指定方的王
boolBeCheck(TBoardb,TSideside)
{//判断是否被“将军"
intx,y,i,j;
TSideoppSide;
GetKingPos