(作者:KX)
(code:C)
/***********************************
源码:中国象棋
作者:王卫祥&KX&2017211836
版本:18060601
代码使用请保留版权
***********************************/
#include <stdio.h>
#include <windows.h>
#include <conio.h>
#define X(x) 6*x+18//棋盘棋子坐标转化为窗口绝对坐标
#define Y(y) 3*y//棋盘棋子坐标转化为窗口绝对坐标
#define Group ((stepCount+1)%2) //当前走方子0红方,1蓝方
#define BoardColor 7,15//棋盘样式
#define ChessColor0 9,15//红方棋子样式
#define ChessColor1 12,15//蓝方棋子样式
#define TipColor 4,15//提醒文字样式
#define Alive (chess[Group][0].x<9) //走子方将军是否几经死亡
typedef struct
{
int x,y;
} Coord;
typedef struct
{
int x,y;//棋子的坐标
int piece;//棋子类型
/**
类型: 0将帅 1仕士 2象相 3馬马 4車车 5炮 6卒兵
**/
} Chess;
void menu();//主菜单
void start();//初始化游戏数据并开始游戏
void setChess();//开始新游戏时初始化所有棋子的坐标类型
void printBoard();//打印棋盘
void printChess();//打印棋子
int gotoxy(int x, int y); //定位光标位置
void control();//游戏时玩家控制
int areaType(int x,int y,int *group,int *no);//判断(x,y)处的类型
void selectTarget();//选中(移动)目标
int canMove(int x,int y);//判断是否可以移动到
void setColor(unsigned short foreColor,unsigned short backGroundColor);//改变打印的颜色
void completeBoard(int x,int y);//补全棋盘
void moveChess(int targetGroup,int targetNo);//将以选中棋子移动到光标处,若该处有棋子将子吃掉
void retract();//悔棋
void printRound();//打印回合数、轮到哪方走子、哪方死棋
void clearSelected();//清除选中棋子信息
void saveGame();//保存游戏
void readGame();//读取游戏
void exitGame();//结束游戏
int stepCount;//存储走的步数(走一步算一步)
Chess chess[2][16];//存放棋子的信息
int x[2],y[2];//存放当前光标位置
int selectedChess=-1;//当前选中的棋子
char piece[2][7][3]={
{"将","仕","象","馬","車","炮","卒"},
{"帅","士","相","马","车","炮","兵"}
};//存放棋子名称
int main(int argc, char *argv[])
{
system("title 中国象棋");
system("mode con cols=69 lines=30");
system("color F0");
while(1)
{
menu();
}
return 0;
}
void menu()
{
char command;
printBoard();
setColor(0,15);
gotoxy(2,3);
printf("1.开始新的游戏\n");
gotoxy(2,4);
printf("2.继续上次游戏\n");
gotoxy(2,5);
printf("0.退出游戏\n");
command=getch();
switch(command)
{
case '1':setChess();start();break;
case '2':readGame();start();break;
case '0':exitGame();break;
}
}
void start()
{
x[0]=x[1]=4;
y[0]=2;
y[1]=7;
gotoxy(X(x[Group]),Y(y[Group]));
printBoard();
setColor(0,15);
gotoxy(2,18);
printf("1.悔棋");
gotoxy(2,19);
printf("2.开始新的游戏");
gotoxy(2,20);
printf("3.退出游戏");
printChess();
while(1)
{
printRound();
control();
selectTarget();
}
}
void printBoard()
{
setColor(BoardColor);
gotoxy(0,0);
printf("┏━━━━━━━┓┏━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┓\n");
printf("┃ ┃ ┃ ┃ ┃╲ ┃ ╱┃ ┃ ┃ ┃\n");
printf("┃ ┃ ┃ ┃ ┃ ╲┃╱ ┃ ┃ ┃ ┃\n");
printf("┃ ┣━━╋━━╋━━╋━━╋━━╋━━╋━━╋━━┫\n");
printf("┃ ┃ ┃ ┃ ┃ ╱┃╲ ┃ ┃ ┃ ┃\n");
printf("┃ ┃ ┃ ┃ ┃╱ ┃ ╲┃ ┃ ┃ ┃\n");
printf("┃ ┣━━╋━━╋━━╋━━╋━━╋━━╋━━╋━━┫\n");
printf("┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃\n");
printf("┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃\n");
printf("┃ ┣━━╋━━╋━━╋━━╋━━╋━━╋━━╋━━┫\n");
printf("┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃\n");
printf("┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃\n");
printf("┃ ┣━━┻━━┻━━┻━━┻━━┻━━┻━━┻━━┫\n");
printf("┃ ┃ 楚 河 ┃\n");
printf("┃ ┃ 汉 界 ┃\n");
printf("┃ ┣━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┫\n");
printf("┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃\n");
printf("┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃\n");
printf("┃ ┣━━╋━━╋━━╋━━╋━━╋━━╋━━╋━━┫\n");
printf("┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃\n");
printf("┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃\n");
printf("┃ ┣━━╋━━╋━━╋━━╋━━╋━━╋━━╋━━┫\n");
printf("┃ ┃ ┃ ┃ ┃╲ ┃ ╱┃ ┃ ┃ ┃\n");
printf("┃ ┃ ┃ ┃ ┃ ╲┃╱ ┃ ┃ ┃ ┃\n");
printf("┃ ┣━━╋━━╋━━╋━━╋━━╋━━╋━━╋━━┫\n");
printf("┃ ┃ ┃ ┃ ┃ ╱┃╲ ┃ ┃ ┃ ┃\n");
printf("┃KX制作 ┃ ┃ ┃ ┃╱ ┃ ╲┃ ┃ ┃ ┃\n");
printf("┗━━━━━━━┛┗━━┻━━┻━━┻━━┻━━┻━━┻━━┻━━┛\n");
return;
}
void setChess()
{
int i,j;
chess[0][0].piece=0;chess[0][0].x=4;chess[0][0].y=0;
chess[0][1].piece=1;chess[0][1].x=3;chess[0][1].y=0;
chess[0][2].piece=1;chess[0][2].x=5;chess[0][2].y=0;
chess[0][3].piece=2;chess[0][3].x=2;chess[0][3].y=0;
chess[0][4].piece=2;chess[0][4].x=6;chess[0][4].y=0;
chess[0][5].piece=3;chess[0][5].x=1;chess[0][5].y=0;
chess[0][6].piece=3;chess[0][6].x=7;chess[0][6].y=0;
chess[0][7].piece=4;chess[0][7].x=0;chess[0][7].y=0;
chess[0][8].piece=4;chess[0][8].x=8;chess[0][8].y=0;
chess[0][9].piece=5;chess[0][9].x=1;chess[0][9].y=2;
chess[0][10].piece=5;chess[0][10].x=7;chess[0][10].y=2;
chess[0][11].piece=6;chess[0][11].x=0;chess[0][11].y=3;
chess[0][12].piece=6;chess[0][12].x=2;chess[0][12].y=3;
chess[0][13].piece=6;chess[0][13].x=4;chess[0][13].y=3;
chess[0][14].piece=6;chess[0][14].x=6;chess[0][14].y=3;
chess[0][15].piece=6;chess[0][15].x=8;chess[0][15].y=3;
chess[1][0].piece=0;chess[1][0].x=4;chess[1][0].y=9;
chess[1][1].piece=1;chess[1][1].x=3;chess[1][1].y=9;
chess[1][2].piece=1;chess[1][2].x=5;chess[1][2].y=9;
chess[1][3].piece=2;chess[1][3].x=2;chess[1][3].y=9;
chess[1][4].piece=2;chess[1][4].x=6;chess[1][4].y=9;
chess[1][5].piece=3;chess[1][5].x=1;chess[1][5].y=9;
chess[1][6].piece=3;chess[1][6].x=7;chess[1][6].y=9;
chess[1][7].piece=4;chess[1][7].x=0;chess[1][7].y=9;
chess[1][8].piece=4;chess[1][8].x=8;chess[1][8].y=9;
chess[1][9].piece=5;chess[1][9].x=1;chess[1][9].y=7;
chess[1][10].piece=5;chess[1][10].x=7;chess[1][10].y=7;
chess[1][11].piece=6;chess[1][11].x=0;chess[1][11].y=6;
chess[1][12].piece=6;chess[1][12].x=2;chess[1][12].y=6;
chess[1][13].piece=6;chess[1][13].x=4;chess[1][13].y=6;
chess[1][14].piece=6;chess[1][14].x=6;chess[1][14].y=6;
chess[1][15].piece=6;chess[1][15].x=8;chess[1][15].y=6;
stepCount=0;
}
void printChess()
{
int i,j;
for(i=0;i<2;i++)
{
if(i==0)
{
setColor(ChessColor0);
}
else
{
setColor(ChessColor1);
}
for(j=0;j<16;j++)
{
if(chess[i][j].x<=8)
{
gotoxy(X(chess[i][j].x),Y(chess[i][j].y));
printf("%s",piece[i][chess[i][j].piece]);
}
}
}
gotoxy(X(x[Group]),Y(y[Group]));
}
int gotoxy(int x, int y) //定位光标位置
{
HANDLE handle; //定义句柄变量handle
COORD coord; //定义结构体coord (坐标系coord)
coord.X = x; //横坐标x
coord.Y = y; //纵坐标y
handle = GetStdHandle(STD_OUTPUT_HANDLE); //获取控制台输出句柄(值为-11)
SetConsoleCursorPosition(handle, coord); //移动光标
}
void setColor(unsigned short foreColor,unsigned short backGroundColor)
{
HANDLE handle=GetStdHandle(STD_OUTPUT_HANDLE);//获取当前窗口句柄
SetConsoleTextAttribute(handle,foreColor+backGroundColor*0x10);//设置颜色
}
int areaType(int tx,int ty,int *group,int *no)
{
int i,j,isFined=0;
for(i=0;i<2 && isFined==0;i++)
{
for(j=0;j<16 && isFined==0;j++)
{
if(chess[i][j].x==tx && chess[i][j].y==ty)
{
isFined=1;
i--;
j--;
}
}
}
if(group!=0)
{
*group=i;
}
if(i==2 && j==16)
{
j=-1;
}
if(no!=0)
{
*no=j;
}
return i;
}
void control()
{
char command;
int oldX,oldY;
while(1)
{
command=getch();
switch(command)
{
case'a':
case 75:if(x[Group]>0) x[Group]--;break;
case'w':
case 72:if(y[Group]>0) y[Group]--;break;
case'd':
case 77:if(x[Group]<8) x[Group]++;break;
case's':
case 80:if(y[Group]<9) y[Group]++;break;
case ' ':
case '\r':if(Alive)return;break;
case '1':retract();break;
case '2':setChess();start();break;
case '3':exitGame();
}
gotoxy(X(x[Group]),Y(y[Group]));
}
}
void selectTarget()
{
int targetGroup,targetNo;
areaType(x[Group],y[Group],&targetGroup,&targetNo);
if(targetGroup==Group)//选中了自己的棋子
{
if(selectedChess!=-1)//之前已经选中了一个棋子
{
clearSelected();
}
selectedChess=targetNo;
setColor(15,Group==0?9:12);
printf("%s",piece[Group][chess[Group][selectedChess].piece]);
}
else
{
moveChess(targetGroup,targetNo);
}
}
void moveChess(int targetGroup,int targetNo)//移动棋子
{
if(canMove(x[Group],y[Group]))
{
completeBoard(chess[Group][selectedChess].x,chess[Group][selectedChess].y);
gotoxy(X(x[Group]),Y(y[Group]));
Group==0?setColor(ChessColor0):setColor(ChessColor1);
printf("%s",piece[Group][chess[Group][selectedChess].piece]);
if(targetGroup!=2)//吃子
{
chess[targetGroup][targetNo].x=9;
}
FILE *record=fopen("data/chess/record.txt","r+");
if(record==NULL)
{
system("cd >data\\chess\\record.txt");
FILE *record=fopen("data/chess/record.txt","r+");
}
fseek(record,16*stepCount,0);
fprintf(record,"%2d %2d %2d %2d %2d\n",selectedChess,chess[Group][selectedChess].x,chess[Group][selectedChess].y,targetNo,x[Group]);
chess[Group][selectedChess].x=x[Group];
chess[Group][selectedChess].y=y[Group];
selectedChess=-1;
fclose(record);
stepCount++;
saveGame();
}
}
int canMove(int x,int y)
{
int can=0,i,j,chessGroup;
chessGroup=areaType(x,y,0,0);
if(selectedChess!=-1 && chessGroup!=Group)
{
if(chess[Group][selectedChess].piece==0)//帅
{
if((x==chess[Group][selectedChess].x && (y==chess[Group][selectedChess].y+1 || y==chess[Group][selectedChess].y-1) && ((y>=7 && y<=9) || (y>=0 && y<=2)))
|| (y==chess[Group][selectedChess].y && (x==chess[Group][selectedChess].x+1 || x==chess[Group][selectedChess].x-1) && x>=3 && x<=5))
{
can=1;
}
else if(x==chess[Group==0?1:0][0].x && x==chess[Group][0].x
&& y==chess[Group==0?1:0][0].y
&& middleChess(x,x,y,chess[Group][0].y)==0)
{
can=1;
}
}
else if(chess[Group][selectedChess].piece==1)//士
{
if(chess[Group][selectedChess].x==4)
{
if(x==3 || x==5)
{
if((Group==0 && (y==0 || y==2))
|| (Group==1 && (y==9 || y==7)))
{
can=1;
}
}
}
else
{
if(x==4)
{
if((Group==0 && y==1) || (Group==1 && y==8))
{
can=1;
}
}
}
}
else if(chess[Group][selectedChess].piece==2)//象
{
if((chess[Group][selectedChess].x==x+2 || chess[Group][selectedChess].x==x-2)
&& (chess[Group][selectedChess].y==y+2 || chess[Group][selectedChess].y==y-2))
{
if((Group==0 && y<=4) || (Group==1 && y>=5))
{
if(areaType((chess[Group][selectedChess].x+x)/2,(chess[Group][selectedChess].y+y)/2,0,0)==2)
{
can=1;
}
}
}
}
else if(chess[Group][selectedChess].piece==3)//马
{
if((chess[Group][selectedChess].x==x+1 || chess[Group][selectedChess].x==x-1)
&& (chess[Group][selectedChess].y==y+2 || chess[Group][selectedChess].y==y-2))
{
if(areaType(chess[Group][selectedChess].x,(chess[Group][selectedChess].y+y)/2,0,0)==2)
{
can=1;
}
}
else if((chess[Group][selectedChess].x==x+2 || chess[Group][selectedChess].x==x-2)
&& (chess[Group][selectedChess].y==y+1 || chess[Group][selectedChess].y==y-1))
{
if(areaType((chess[Group][selectedChess].x+x)/2,chess[Group][selectedChess].y,0,0)==2)
{
can=1;
}
}
}
else if(chess[Group][selectedChess].piece==4)//车
{
if(middleChess(chess[Group][selectedChess].x,x,chess[Group][selectedChess].y,y)==0)
{
can=1;
}
}
else if(chess[Group][selectedChess].piece==5)//炮
{
j=middleChess(chess[Group][selectedChess].x,x,chess[Group][selectedChess].y,y);
if((j==1 && areaType(x,y,0,0)!=2) || (j==0 && areaType(x,y,0,0)==2))
{
can=1;
}
}
else if(chess[Group][selectedChess].piece==6)//卒
{
if(Group==0)
{
if((x==chess[Group][selectedChess].x && y==chess[Group][selectedChess].y+1)
|| (y>=5 && y==chess[Group][selectedChess].y && (x==chess[Group][selectedChess].x-1 || x==chess[Group][selectedChess].x+1)))
{
can=1;
}
}
else if(Group==1)
{
if((x==chess[Group][selectedChess].x && y==chess[Group][selectedChess].y-1)
|| (y<=4 && y==chess[Group][selectedChess].y && (x==chess[Group][selectedChess].x-1 || x==chess[Group][selectedChess].x+1)))
{
can=1;
}
}
}
}
return can;
}
int middleChess(int x1,int x2,int y1,int y2)
{
int t=-1,num=0,i,j;
if(x1!=x2 && y1!=y2)
{
return -1;
}
if(x1!=x2 && y1==y2)
{
t=y1;
y1=x1;
y2=x2;
x1=x2=t;
}
if(y1<y2)
{
j=1;
}
else
{
j=-1;
}
for(i=y1+j;i!=y2;)
{
if((t==-1 && areaType(x1,i,0,0)!=2) ||(t!=-1 && areaType(i,x1,0,0)!=2))
{
num++;
}
i+=j;
}
return num;
}
void retract()
{
if(stepCount>0)
{
int movedChessNo,originX,originY,eatChessNo,eatX;
FILE *record=fopen("data/chess/record.txt","r");
if(record==NULL)
{
system("cd >data\\chess\\record.txt");
}
else
{
if(selectedChess!=-1)//之前已经选中了一个棋子
{
clearSelected();
}
stepCount--;
fseek(record,stepCount*16,0);
fscanf(record,"%d%d%d%d%d",&movedChessNo,&originX,&originY,&eatChessNo,&eatX);
completeBoard(chess[Group][movedChessNo].x,chess[Group][movedChessNo].y);
gotoxy(X(originX),Y(originY));
Group==0?setColor(ChessColor0):setColor(ChessColor1);
printf("%s",piece[Group][chess[Group][movedChessNo].piece]);
chess[Group][movedChessNo].x=originX;
chess[Group][movedChessNo].y=originY;
if(eatChessNo!=-1)
{
chess[Group==0?1:0][eatChessNo].x=eatX;
gotoxy(X(chess[Group==0?1:0][eatChessNo].x),Y(chess[Group==0?1:0][eatChessNo].y));
Group==0?setColor(ChessColor1):setColor(ChessColor0);
printf("%s",piece[Group==0?1:0][chess[Group==0?1:0][eatChessNo].piece]);
}
x[Group]=originX;
y[Group]=originY;
fclose(record);
}
printRound();
}
}
void completeBoard(int x,int y)
{
gotoxy(X(x),Y(y));
setColor(BoardColor);
if(x==0)
{
if(y==0)
{
printf("┏");
}
else if(y==9)
{
printf("┗");
}
else
{
printf("┣");
}
}
else if(x==8)
{
if(y==0)
{
printf("┓");
}
else if(y==9)
{
printf("┛");
}
else
{
printf("┫");
}
}
else
{
if(y==0 || y==5)
{
printf("┳");
}
else if(y==9 || y==4)
{
printf("┻");
}
else
{
printf("╋");
}
}
}
void saveGame()
{
//remove("data/chess/save.dat");
FILE *fp=fopen("data/chess/save.dat","w");
fwrite(chess,sizeof(Chess),32,fp);
fwrite(&stepCount,sizeof(int),1,fp);
fclose(fp);
}
void readGame()
{
FILE *fp=fopen("data/chess/save.dat","r");
if(fp!=NULL)
{
fread(chess,sizeof(Chess),32,fp);
fread(&stepCount,sizeof(int),1,fp);
fclose(fp);
}
else
{
//system("cd >data\\chess\\save.dat.txt");
setChess();
}
}
void printRound()
{
if(Alive)
{
gotoxy(3,5);
setColor(TipColor);
printf("%s走子",Group==0?"蓝方":"红方");
gotoxy(3,3);
printf("第%3d回合",stepCount/2+1);
}
else
{
gotoxy(3,5);
//setColor(TipColor);
printf("%s死棋",Group==0?"蓝方":"红方");
}
gotoxy(X(x[Group]),Y(y[Group]));
}
void clearSelected()
{
Group==0?setColor(ChessColor0):setColor(ChessColor1);
gotoxy(X(chess[Group][selectedChess].x),Y(chess[Group][selectedChess].y));
printf("%s",piece[Group][chess[Group][selectedChess].piece]);//清除之前选中的颜色
selectedChess=-1;
gotoxy(X(x[Group]),Y(y[Group]));
}
void exitGame()
{
exit(0);
}
/****Powered by KX****/
(/code)