/***********************************
	源码:中国象棋 
	作者:王卫祥&KX&2017211836
	版本:18060601
	代码使用请保留版权 
***********************************/

#include <stdio.h>
#include <windows.h>
#include <conio.h>
#include <unistd.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 0,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();//结束游戏
void createEnvironment();

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");
	createEnvironment();
	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.退出游戏");
	gotoxy(2,9);
	setColor(2,15);
	printf("上移:W或↑");
	gotoxy(2,10);
	printf("下移:S或↓");
	gotoxy(2,11);
	printf("左移:A或←");
	gotoxy(2,12);
	printf("右移:D或→");
	gotoxy(2,13);
	printf("选中:空格或回车");
	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("┃www.newv┃  ┃  ┃  ┃ ╱┃╲ ┃  ┃  ┃  ┃\n");
	printf("┃ iew.top┃  ┃  ┃  ┃╱ ┃ ╲┃  ┃  ┃  ┃\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?0: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)//判断可否移动至(x,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
	{
		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 createEnvironment(){
	if(access("data/chess/",F_OK)==-1)//判断文件夹是否存在
		system("md data\\chess");//建立文件夹 
	fopen("data/chess/record.txt","a");//判断文件是否存在,不存在则创建 
	return;
}

void exitGame()
{
	exit(0);
}

/****Powered by KX****/

/*****KX收藏站*****/

运行效果:

C语言中国象棋

下载EXE文件


我一直在开辟我的天空