2021-09-02我的象棋

@我的象棋

小熊猫C++

这是我的第一个编辑器

学习编辑了一些小游戏

  1. 我的象棋
    在这里插入图片描述
/*
	2022.4.18 重写象棋
*/

#include <stdio.h>
#include <windows.h>
#include <graphics.h>

#define GZ 65              //棋盘格子大小   
#define BIAN 90            //棋盘边到屏幕边距离 
#define X(i) (BIAN+GZ*i)   //i表示0~8 横向坐标
#define Y(i) (BIAN+GZ*i)   //i表示0~9 纵向坐标
#define R (GZ/2-5)         //棋子圆形半径 
#define Row 10             //棋盘行
#define Col 9              //棋盘列
#define Num 32             //棋子总数
#define weight X(8) + X(3) //窗口宽
#define high   Y(9) + BIAN //窗口高

char mz[] = {'1', '2', '3', '4', '5', '6', '7', '8', '9'};
const char *nz[] = {"一", "二", "三", "四", "五", "六", "七", "八", "九"};
enum Pieces {NONE = -1,,,,,,,,,,,,,,};  //NONE表示无棋子
const char *chessName[] = {"车", "马", "象", "士", "将", "炮", "兵", "車", "馬", "相", "仕", "帅", "砲", "卒"};  //[0~13]
bool is_Select;    //选棋子
bool zoudong;      //是否走动
bool gameover;     //判断是否游戏结束
bool flag;         //黑红交替用
enum {zou, chi};
//int steps = 0;          //步数 steps

//棋盘格点元素
typedef struct QMap {
	int x, y, Name, ID;
	DWORD type;
} QMap;                  //定义棋盘名

//棋盘矩阵元素
typedef struct {
	QMap data[Num];
	int  m, n, num;
} chessMartix;           //定义棋盘矩阵

QMap Map[Row][Col];     //棋盘 Map[10][9]
QMap M[Num - 1];        //32个棋子 M[0~31]

//-------------------------------------------------
QMap N[Num - 3];        //存放被吃棋子最多29个 栈N[0~28]
int top = -1;        //栈顶数
//入栈N[]
int pushN(QMap *O, int top, QMap E) {
	O[++(top)] = E;
	printf("被吃棋子:%s  top=%d\n", chessName[N[top].Name], top);
	return top;
}
//出栈N[]
int popN(int top) {
	if (top == -1) {
		printf("空栈");
		return -1;
	}
	printf("top=%d\n", top);
	top--;
	return top;
}
//--------------------------------------------------

//棋谱链表节点结构 前指针,后指针,ID,走前坐标,走后坐标,是走是吃。
typedef struct qipulink {
	struct qipulink *prior;
	int zouchi;
	int ID;
	int x;
	int y;
	int cx;
	int cy;
	struct qipulink *next;
} link;

//初始化棋谱链 开始只有一个没用的首节点
link *initqipu(link *qipu) {
	//创建棋谱首元节点
	qipu = (link*)malloc(sizeof(link));
	//对节点初始化
	qipu->prior = NULL;
	qipu->zouchi = zou;
	qipu->ID = -2;
	qipu-> cx = -1;
	qipu-> cy = -1;
	qipu-> x = -2;
	qipu-> y = -2;
	qipu->next = NULL;
	return qipu;
}

//插入棋谱链新节点
link *insterLink(link *qipu, int x, int y, int cx, int cy, int ID, int zouchi) {
	//创建新节点
	link *temp = (link*)malloc(sizeof(link));
	temp->prior = NULL;
	temp->next  = NULL;
	temp->x  = x;
	temp->y  = y;
	temp->cx = cx;
	temp->cy = cy;
	temp->ID = ID;
	temp->zouchi = zouchi;
	//定义新指针p 指向qipu
	link* p = qipu;
	if (p == NULL) {
		p = temp;
		printf("初始化失败!\n");
	} else {
		//链接新节点 到qipu尾部
		while (p->next) {      //找到p尾结点
			p = p->next;
		}
		temp->next = p->next;
		temp->prior = p;
		p->next = temp;
	}
	return p;
}

//控制台棋谱链显示
void displayqipu(link *qipu) {
	link *temp = qipu;
	while (temp != NULL) {
		if (temp->next == NULL) {
			printf("[%d %d] [%d %d] [%d]\n", temp-> x, temp-> y, temp->cx, temp->cy, temp->zouchi);
		} else {
			printf("[%d %d] [%d %d] [%d] <=> ", temp-> x, temp-> y, temp->cx, temp->cy, temp->zouchi);
		}
		temp = temp->next;
	}
	printf("-----------------------------------------------------\n\n");
}

//初始化 Map[][], main{ chessMartix *Q}
void initMap(chessMartix* Q) {
	//初始化棋子M[]
	for (int j = 0; j < Num; j++) {                //0~31 x,y,id,name,type
		int temp = 0;                              //记录0~31棋子编号对应的象棋名字编号
		if (j < 16) {                              //----------前16个棋子--------------
			if (j < 4) {
				temp = j;                          //0 1 2 3 4
			} else if (j < 9) {
				temp = 8 - j;                      //3 2 1 0
			} else if (j == 9 || j == 10) {
				temp = 5;                          //5
			} else {
				temp = 6;                          //6
			}
			M[j].type = BLACK;                     //为黑色
		} else {                                   //-----------后16个棋子---------------
			int k = j - 16;
			if (k < 4) {
				temp = 7 + k;                      //7 8 9 10 11
			} else if (k < 9) {
				temp = 7 + 8 - k;                  //10 9 8 7
			} else if (k  == 9 || k  == 10) {
				temp = 7 + 5;                      //12
			} else {
				temp = 7 + 6;                      //13
			}
			M[j].type = RED;                       //为红色
		}
		M[j].Name = temp;    /*象棋名字编号0 1 2 3 4 3 2 1 0 5 6 7 8 9 10 11 10 9 8 7 12 13*/
		M[j].ID = j;         //0~31
		M[j].x = 0;
		M[j].y = 0;
	}
	//初始化棋盘Map[][],以及各棋子的位置颜色
	for (int j = 0; j < Row; j++) {
		for (int i = 0; i < Col; i++) {
			Map[j][i].Name = -1;
			Map[j][i].ID = -1;
			Map[j][i].x = i;
			Map[j][i].y = j;
		}
	}
	for (int j = 0; j < Row; j++) {
		for (int i = 0; i < Col; i++) {
			//--------------------------------------------
			if (j == 0) {                     //0 1 2 3 4 3 2 1 0
				Map[j][i].Name = M[i].Name;
				Map[j][i].ID = M[i].ID;
			}
			if (j == 2 && i == 1) {           //  5
				Map[j][i].Name = M[9].Name;
				Map[j][i].ID = M[9].ID;
			}
			if ((j == 2 && i == 7)) {          //              5
				Map[j][i].Name = M[10].Name;
				Map[j][i].ID = M[10].ID;
			}
			if (j == 3 && i < 5) {             //6   6   6   6   6
				Map[j][(i * 2)].Name = M[11 + i].Name;
				Map[j][(i * 2)].ID = M[11 + i].ID;
			}
			//------------------------------------------------
			if (9 - j == 0) {                   //7  8 9 10 11 10 9 8 7
				Map[j][i].Name = M[16 + i].Name;
				Map[j][i].ID = M[16 + i].ID;
			}
			if (9 - j == 2 && i == 1) {         //  12
				Map[j][i].Name = M[16 + 9].Name;
				Map[j][i].ID = M[16 + 9].ID;
			}
			if ((9 - j == 2 && i == 7)) {        //                12
				Map[j][i].Name = M[16 + 10].Name;
				Map[j][i].ID = M[16 + 10].ID;
			}
			if (9 - j == 3 && i < 5) {           //13   13   13   13   13
				Map[j][i * 2].Name = M[16 + 11 + i].Name;
				Map[j][i * 2].ID = M[16 + 11 + i].ID;
			}
		}
	}
	for (int j = 0; j < Row; j++) {
		for (int i = 0; i < Col; i++) {
			if (Map[j][i].ID < 16 && Map[j][i].ID >= 0) {
				Map[j][i].type = BLACK;
			} else if (Map[j][i].ID < Num && Map[j][i].ID >= 16) {
				Map[j][i].type = RED;
			} else {
				Map[j][i].type = BLUE;
			}
		}
	}
	//初始化矩阵Q 稀疏矩阵存储32个棋子
	int nn = 0;
	for (int j = 0; j < Row; j++) {
		for (int i = 0; i < Col; i++) {
			if (Map[j][i].Name != -1) {
				Q->data[nn].Name = Map[j][i].Name;
				Q->data[nn].ID = Map[j][i].ID;
				Q->data[nn].y = j;
				Q->data[nn].x = i;
				nn++;
			}
		}
	}
}
//控制台矩阵显示1
void displayQ(chessMartix * Q) {
	for (int i = 0; i < Q->n; i++) {
		for (int j = 0; j < Q->m; j++) {
			int value = 0;
			for (int k = 0; k < Q->num; k++) {
				if (i == Q->data[k].y && j == Q->data[k].x) {
					printf("%-4d", Q->data[k].Name);
					value = 1;
					break;
				}
			}
			if (value == 0) {
				printf("*   ");
			}
		}
		printf("\n\n");
	}
}
//隐藏控制台光标功能
void recursor() {
	HANDLE hout;
	hout = GetStdHandle(STD_OUTPUT_HANDLE);
	COORD coord;
	coord.X = 0;
	coord.Y = 0;
	SetConsoleCursorPosition(hout, coord);
}
//控制台显示2
void show() {
	//system("cls");
	recursor();
	for (int i = 0; i < Row; i++) {
		for (int j = 0; j < Col; j++) {
			printf("%-4d", Map[i][j].ID);
		}
		printf("\n\n");
	}
	printf("top=%d\a\n\n", top);    //  \a是响铃符
}
//画棋盘
void huaqipan() {
	setcolor(GREEN);
	for (int x = X(0); x <= X(8); x += GZ) {
		line(x, Y(0), x, Y(4)); /*上半和下半【竖】*/
		line(x, Y(5), x, Y(9));
	}
	line(X(0), Y(4), X(0), Y(5)); /*【左】【竖】*/
	line(X(8), Y(4), X(8), Y(5)); /*【右】【竖】*/

	for (int y = Y(0); y <= Y(9); y += GZ) {
		line(X(0), y, X(8), y);   /*【行】*/
	}

	for (int i = X(1); i <= X(7); i += GZ * 6) {
		for (int j = Y(2); j <= Y(7); j += GZ * 5) {

			/*画星号【行】*/
			line(i - GZ / 4, j - GZ / 16, i - GZ / 16, j - GZ / 16);
			line(i + GZ / 4, j - GZ / 16, i + GZ / 16, j - GZ / 16);
			line(i - GZ / 4, j + GZ / 16, i - GZ / 16, j + GZ / 16);
			line(i + GZ / 4, j + GZ / 16, i + GZ / 16, j + GZ / 16);

			/*画星号【竖】*/
			line(i - GZ / 16, j - GZ / 16, i - GZ / 16, j - GZ / 4);
			line(i + GZ / 16, j - GZ / 16, i + GZ / 16, j - GZ / 4);
			line(i - GZ / 16, j + GZ / 16, i - GZ / 16, j + GZ / 4);
			line(i + GZ / 16, j + GZ / 16, i + GZ / 16, j + GZ / 4);
		}
	}

	line(X(3), Y(2), X(5), Y(0));  /*上【将位】*/
	line(X(3), Y(0), X(5), Y(2));

	line(X(3), Y(7), X(5), Y(9));  /*下帅位*/
	line(X(3), Y(9), X(5), Y(7));

	setfillcolor(CYAN);
	bar(X(0) + GZ / 40, Y(4) + GZ / 40, X(8) - GZ / 40, Y(5) - GZ / 40); /*棋盘中间*/

	rectangle(X(0) - BIAN / 2, Y(0) - BIAN + 10, X(8) + BIAN / 2, Y(9) + BIAN - 10); /*棋盘外框*/
	rectangle(X(0) - BIAN / 2 + 3, Y(0) - BIAN + 10 + 3, X(8) + BIAN / 2 - 3, Y(9) + BIAN - 10 - 3); /*棋盘外框*/

	//棋盘纵向编号标注
	for (int i = 0; i < Col; i++) {
		//{"一", "二", "三", "四", "五", "六", "七", "八", "九"};
		setcolor(RED);
		setfont(GZ / 3, 0, "隶书");
		outtextxy(X(i) - BIAN * 1 / 8, Y(10) - BIAN * 4 / 10, nz[8 - i]);
		//{'1', '2', '3', '4', '5', '6', '7', '8', '9'};
		setfont(GZ / 2, 0, "隶书");
		setcolor(EGERGB(0x4E, 0xC9, 0xB0));
		outtextxy(X(i) - BIAN * 1 / 10, Y(0) - BIAN * 8 / 10, mz[i]);
	}

	setbkmode(TRANSPARENT);
	setcolor(RED);
	setfont(GZ / 2, 0, "隶书");
	outtextxy(X(2) + 5, Y(4) + GZ / 4, "楚河        汉界");  /*字体坐标*/

	setfont(GZ, 0, "隶书");
	outtextxy(X(9) + BIAN / 2, GZ / 4, "中国");              /*标题输出*/
	outtextxy(X(9) + BIAN / 2, GZ + GZ / 4, "象棋");

	setcolor(WHITE);                                         /*棋谱输出区*/
	rectangle(X(10) - GZ / 3, Y(3), X(12) - GZ / 3, Y(9));
}
//画单个棋子
void huaqizi(int y, int x, const char* zi, DWORD hh) {
	setcolor(MEDIUMSPRINGGREEN);
	setfillcolor(GREENYELLOW);
	fillellipse(X(x), Y(y), R, R, NULL);
	setfillcolor(YELLOW);
	fillellipse(X(x), Y(y), R - 4, R - 4, NULL);
	setcolor(hh);
	setfont(GZ * 6 / 10, 0, "隶书");
	outtextxy(X(x) - (GZ * 6 / 10) / 2, Y(y) - (GZ * 6 / 10) / 2, zi);
}
//画选中棋子
void xuanqizi(int x, int y, const char* zi, int hh) {
	setcolor(MEDIUMSPRINGGREEN);
	setfillcolor(BLACK);
	fillellipse(X(x), Y(y), R, R, NULL);
	setfillcolor(YELLOW);
	fillellipse(X(x), Y(y), R - 4, R - 4, NULL);
	setfont(GZ * 6 / 10, 0, "隶书");
	setcolor(hh);
	outtextxy(X(x) - (GZ * 6 / 10) / 2, Y(y) - (GZ * 6 / 10) / 2, zi);
}
//画所有棋子1
void draw() {
	cleardevice();
	huaqipan();
	for (int i = 0; i < Row; i++) {
		for (int j = 0; j < Col; j++) {
			if (Map[i][j].Name != -1 ) {
				huaqizi(i, j, chessName[Map[i][j].Name], Map[i][j].type);
			}
		}
	}
}
//画所有棋子2
void draw1(chessMartix * Q) {
	huaqipan();
	for (int k = 0; k < Q->num; k++) {
		huaqizi(Q->data[k].y, Q->data[k].x,  chessName[Q->data[k].Name], Map[Q->data[k].y][Q->data[k].x].type);
	}

}
//画选择“再来”“退出”
void drawxuanze(int i) {
	setcolor(WHITE);
	if (i == 2) {    //标注 退出
		rectangle(X(10) + GZ * 7 / 10, Y(1) + GZ * 2 / 10, X(11) + GZ * 6 / 10, Y(1) + GZ * 7 / 10 );
	} else if (i == 3) { //标注 再来
		rectangle(X(9) + GZ * 7 / 10, Y(1) + GZ * 2 / 10, X(10) + GZ * 6 / 10, Y(1) + GZ * 7 / 10 );
	} else if (i == 1) { //不 标注
		setcolor(BLACK);
		rectangle(X(10) + GZ * 7 / 10, Y(1) + GZ * 2 / 10, X(11) + GZ * 6 / 10, Y(1) + GZ * 7 / 10 );
		rectangle(X(9) + GZ * 7 / 10, Y(1) + GZ * 2 / 10, X(10) + GZ * 6 / 10, Y(1) + GZ * 7 / 10 );
	}
}
//棋谱长度
int qipulength(link* qipu) {
	int length = 0;
	link* p = qipu->next;
	while (p) {
		p = p->next;
		length++;
	}
	return length;
}
//画棋谱 棋谱输出
void huaqipu(link *qipu) {
	setfont(GZ / 4, 0, "隶书");
	setcolor(WHITE);
	char str1[30];
	link* temp = qipu->next;
	int m = qipulength(qipu);
	int num_rows = 18;         //显示qipu的总行数
	if (m > num_rows) {
		while (temp->next) {
			temp = temp->next;
		}
		int x = num_rows;
		while (--x) {
			temp = temp->prior;
		}
		for (int i = 0; i < num_rows; i++) {                    // qipu显示超过18行时
			if (temp->ID >= 0 && temp->ID < 16) {               // 黑棋
				if (temp->y == temp->cy) {                      // 平着走
					sprintf(str1, "%s %c  平  %c", chessName[M[temp->ID].Name], mz[(temp->x)], mz[(temp->cx )]);
				} else if (temp->cx == temp->x) {               // 竖着走
					if (temp->cy > temp->y) {
						sprintf(str1, "%s %c  进  %c", chessName[M[temp->ID].Name], mz[(temp->x)], mz[(temp->cy - temp->y) - 1]);
					} else {
						sprintf(str1, "%s %c  退  %c", chessName[M[temp->ID].Name], mz[(temp->x)], mz[(temp->y - temp->cy) - 1]);
					}
				} else {                                         // 斜着走
					if (temp->cy > temp->y) {
						sprintf(str1, "%s %c  进  %c", chessName[M[temp->ID].Name], mz[(temp->x)], mz[(temp->cx )]);
					} else {
						sprintf(str1, "%s %c  退  %c", chessName[M[temp->ID].Name], mz[(temp->x)], mz[(temp->cx )]);
					}
				}
			}
			if (temp->ID >= 16 && temp->ID < 32) {              // 红棋
				if (temp->y == temp->cy) {                      // 平着走
					sprintf(str1, "%s %s 平 %s", chessName[M[temp->ID].Name], nz[8 - (temp->x)], nz[8 - (temp->cx)]);
				} else if (temp->cx == temp->x) {               // 竖着走
					if (temp->cy < temp->y) {
						sprintf(str1, "%s %s 进 %s", chessName[M[temp->ID].Name], nz[8 - (temp->x)], nz[(temp->y - temp->cy) - 1]);
					} else {
						sprintf(str1, "%s %s 退 %s", chessName[M[temp->ID].Name], nz[8 - (temp->x)], nz[(temp->cy - temp->y) - 1]);
					}
				} else {                                         // 斜着走
					if (temp->cy < temp->y) {
						sprintf(str1, "%s %s 进 %s", chessName[M[temp->ID].Name], nz[8 - (temp->x)], nz[8 - (temp->cx)]);
					} else {
						sprintf(str1, "%s %s 退 %s", chessName[M[temp->ID].Name], nz[8 - (temp->x)], nz[8 - (temp->cx)]);
					}
				}
			}
			xyprintf(X(10) + GZ / 10, Y(3) + GZ / 10 + (GZ / 4 + 5) * i, str1);
			temp = temp->next;
		}
	} else {
		for (int i = 0; i < m; i++) {                           // qipu显示不满18行时
			if (temp->ID >= 0 && temp->ID < 16) {               // 黑棋
				if (temp->y == temp->cy) {                      // 平着走
					sprintf(str1, "%s %c  平  %c", chessName[M[temp->ID].Name], mz[(temp->x)], mz[(temp->cx)]);
				} else if (temp->cx == temp->x) {               // 竖着走
					if (temp->cy > temp->y) {
						sprintf(str1, "%s %c  进  %c", chessName[M[temp->ID].Name], mz[(temp->x)], mz[(temp->cy - temp->y) - 1]);
					} else {
						sprintf(str1, "%s %c  退  %c", chessName[M[temp->ID].Name], mz[(temp->x)], mz[(temp->y - temp->cy) - 1]);
					}
				} else {                                         // 斜着走
					if (temp->cy > temp->y) {
						sprintf(str1, "%s %c  进  %c", chessName[M[temp->ID].Name], mz[(temp->x)], mz[(temp->cx)]);
					} else {
						sprintf(str1, "%s %c  退  %c", chessName[M[temp->ID].Name], mz[(temp->x)], mz[(temp->cx)]);
					}
				}
			}
			if (temp->ID >= 16 && temp->ID < 32) {              // 红棋
				if (temp->y == temp->cy) {                      // 平着走
					sprintf(str1, "%s %s 平 %s", chessName[M[temp->ID].Name], nz[8 - (temp->x)], nz[8 - (temp->cx)]);
				} else if (temp->cx == temp->x) {               // 竖着走
					if (temp->cy < temp->y) {
						sprintf(str1, "%s %s 进 %s", chessName[M[temp->ID].Name], nz[8 - (temp->x)], nz[(temp->y - temp->cy) - 1]);
					} else {
						sprintf(str1, "%s %s 退 %s", chessName[M[temp->ID].Name], nz[8 - (temp->x)], nz[(temp->cy - temp->y) - 1]);
					}
				} else {                                         // 斜着走
					if (temp->cy < temp->y) {
						sprintf(str1, "%s %s 进 %s", chessName[M[temp->ID].Name], nz[8 - (temp->x)], nz[8 - (temp->cx)]);
					} else {
						sprintf(str1, "%s %s 退 %s", chessName[M[temp->ID].Name], nz[8 - (temp->x)], nz[8 - (temp->cx)]);
					}
				}
			}
			xyprintf(X(10) + GZ / 10, Y(3) + GZ / 10 + (GZ / 4 + 5) * i, str1);
			temp = temp->next;
		}
	}
}
//走吃棋子
void zouchi(link * qipu, int x, int y, int cx, int cy) {
	int zouchi;
	QMap temp;
	temp = Map[y][x];
	//判断是走是吃,并保存被吃棋子
	if (Map[cy][cx].Name != NONE && Map[y][x].type != Map[cy][cx].type) {
		zouchi = chi;
		top = pushN(N, top, Map[cy][cx]);         //被吃棋子存入N[]
	} else {
		zouchi = zou;
	}
	//走棋子后的元素变更
	Map[cy][cx] = temp ;     //新棋位改为新棋子颜色 ID Name
	Map[cy][cx].x = cx;      //取得新坐标
	Map[cy][cx].y = cy;
	Map[y][x].Name = NONE;   //旧棋位 跟新为 NONE
	Map[y][x].ID = NONE;
	zoudong = true;	         //棋子已走动
	qipu = insterLink(qipu, x, y, cx, cy, temp.ID, zouchi);   //登记入棋谱
}
//游戏结束
void Gameover() {   //根据棋盘中 将 帅 的存在,给出gameover的值 true
	int i = 1;
	int j = 1;
	for (int m = 0; m < Row; m++) {
		for (int n = 0; n < Col; n++) {
			if (Map[m][n].Name == 4) {         //数组Map中找到4,表示红将还没死
				i = 0;
			}
			if (Map[m][n].Name == 11) {        //数组Map中找到11,表示黑将还没死
				j = 0;
			}
		}
	}
	//游戏结束后给出结果和选择
	if (i || j) {
		setfont(GZ * 6 / 10, 0, "隶书");
		if (i) {                                 //i=1 则黑棋胜
			setcolor(RED);
			outtextxy(X(9) + GZ / 2, Y(2), "=红旗胜=");
		}
		if (j) {                                 //j=1 则红棋胜
			setcolor(BLUE);
			outtextxy(X(9) + GZ / 2, Y(2), "=黑旗胜=");
		}
		setcolor(WHITE);
		setfont(GZ * 3 / 10, 0, "隶书");     //改变字体大小
		outtextxy(X(9) + GZ * 5 / 10, Y(1) + GZ * 3 / 10, "  再来");
		outtextxy(X(9) + GZ * 15 / 10, Y(1) + GZ * 3 / 10, "  退出");
		gameover = true;
	}
}
//走(车 炮)判断
int is_go1(int x, int y, int cx, int cy) {
	int count = NONE;       //返回值 走棋子之间的棋子数 0 1 表示车可以走吃,0 2 表示砲可以走吃。
	if (y == cy && x < cx) {
		for (int i = x ; i <= cx; i++) {
			if (Map[y][i].Name != NONE) {
				count++;
			};
		}
	} else if (y == cy && x > cx) {
		for (int i = x ; i >= cx; i--)  {
			if (Map[y][i].Name != NONE) {
				count++;
			};
		}
	} else if (x == cx && y < cy) {
		for (int i = y ; i <= cy; i++) {
			if (Map[i][x].Name != NONE) {
				count++;
			};
		}
	} else if (x == cx && y > cy) {
		for (int i = y ; i >= cy; i--) {
			if (Map[i][x].Name != NONE) {
				count++;
			};
		}
	}
	return count;
}
//走(马) 判断
int is_go2(int x, int y, int cx, int cy) {
	int count = NONE;
	if (5 == (abs(x - cx)*abs(x - cx) + abs(y - cy)*abs(y - cy))) {  //马可以走的八个点的距离为5
		if (((2 == (x - cx)) && (Map[y][x - 1].Name != NONE)) ||
		    ((2 == (cx - x)) && (Map[y][x + 1].Name != NONE)) ||
		    ((2 == (y - cy)) && (Map[y - 1][x].Name != NONE)) ||
		    ((2 == (cy - y)) && (Map[y + 1][x].Name != NONE))) {     //憋马脚的四个情况
			count = NONE;
		} else if (Map[cy][cx].Name != NONE) {
			count = 1;                                               //吃
		} else {
			count = 0;                                               //走
		}
	}
	return count;
}
//走(象)判断
int is_go3(int x, int y, int cx, int cy) {
	int count = NONE;
	if (8 == (abs(x - cx)*abs(x - cx) + abs(y - cy)*abs(y - cy))) {                    //象可以走的四个点的距离为8
		if (((2 == (x - cx) && 2 == (y - cy)) && (Map[y - 1][x - 1].Name != NONE)) ||
		    ((2 == (cx - x) && 2 == (y - cy)) && (Map[y - 1][x + 1].Name != NONE)) ||
		    ((2 == (cx - x) && 2 == (cy - y)) && (Map[y + 1][x + 1].Name != NONE)) ||
		    ((2 == (x - cx) && 2 == (cy - y)) && (Map[y + 1][x - 1].Name != NONE))) {  //憋象眼的四个情况
			count = NONE;
		} else if (Map[cy][cx].Name != NONE) {
			count = 1;                                                                 //吃
		} else {
			count = 0;                                                                 //走
		}
	}
	return count;
}
//走(士)判断
int is_go4(int x, int y, int cx, int cy) {
	int count = NONE;
	if (2 == (abs(x - cx)*abs(x - cx) + abs(y - cy)*abs(y - cy)) &&
	    (cx <= 5 && cx >= 3) && ((cy >= 0 && cy <= 2) || (cy <= 9 && cy >= 7))) {     //士可以走的四个点的距离为2
		if (Map[cy][cx].Name != NONE) {
			count = 1;                                                                //吃
		} else {
			count = 0;                                                                //走
		}
	}
	return count;
}
//检查是否对老将了
int duilaojiang() {
	int count = 0;
	int x, y;
	int cx, cy;
	for (int m = 0; m < Row; m++) {      //从Map中找出(将)与(帅)的坐标并记录
		for (int n = 0; n < Col; n++) {
			if (Map[m][n].Name == 4) {
				x = n;
				y = m;
			}
			if (Map[m][n].Name == 11) {
				cx = n;
				cy = m;
			}
		}
	}
	if (x == cx) {  //检查(将)与(帅)之间有没有棋子 count=2 为没棋子,即为对老将了
		for (int i = y; i <= cy; i++) {
			if (Map[i][x].Name != NONE) {
				count++;
			}
		}
	}
	return count;
}
//走(将)判断
int is_go5(int x, int y, int cx, int cy) {
	int count = NONE;
	//对老将且目标棋位只能是有棋子,即只能将吃帅或帅吃将,不能走到其他没棋子的位置
	if (duilaojiang() == 2 && Map[cy][cx].Name != NONE) {
		count = 2;
	}
	//将可以走的四个点的距离为1 且将帅的走动范围在田字格内
	if (1 == (abs(x - cx)*abs(x - cx) + abs(y - cy)*abs(y - cy)) &&
	    (cx <= 5 && cx >= 3) && ((cy >= 0 && cy <= 2) || (cy <= 9 && cy >= 7))) {
		if (Map[cy][cx].Name != NONE ) {
			if (Map[y][x].type != Map[cy][cx].type) {
				count = 1;              //吃
			}
		} else {
			count = 0;                  //走
		}
	}
	return count;
}
//走(兵)判断
int is_go6(int x, int y, int cx, int cy) {
	int count = NONE;
	//卒只能向前的1个点走且过河后可以横着走的距离为1
	if ((1 == (abs(x - cx)*abs(x - cx) + abs(y - cy)*abs(y - cy)))) {   //能走一格,有四个点
		if (M[Map[y][x].ID].type == BLACK && y < 5 && x == cx) {        //黑棋 y<5表示没过河,x==cx表示只能竖着走
			if (cy > y) {                                               //黑棋 向前走
				if (Map[cy][cx].Name != NONE) {
					count = 1;                     //吃
				} else {
					count = 0;                     //走
				}
			} else {                                                     //不能后退
				count = NONE;
			}
		} else if (Map[y][x].type == BLACK && y > 4) {                   //黑棋过河后 不限制x==cx 就可以横着走
			if (cy >= y) {                                               //cy>=y表示可以向前走,可以横着走,不能后退
				if (Map[cy][cx].Name != NONE) {
					count = 1;                     //吃
				} else {
					count = 0;                     //走
				}
			} else {                                                     //不能后退
				count = NONE;
			}
		} else if (Map[y][x].type == RED && y > 4 && x == cx) {          //红棋没过河处理
			if (cy < y) {
				if (Map[cy][cx].Name != NONE) {
					count = 1;                     //吃
				} else {
					count = 0;                     //走
				}
			} else {
				count = NONE;
			}
		} else if (Map[y][x].type == RED && y < 5) {                      //红棋过河处理
			if (cy <= y) {
				if (Map[cy][cx].Name != NONE) {
					count = 1;                     //吃
				} else {
					count = 0;                     //走
				}
			} else {
				count = NONE;
			}
		}
	}
	return count;
}
//走棋子
void zouqizi(link * qipu, int x, int y, int cx, int cy) {
	zoudong = false;                      //走过了,为了flag红黑棋的选择
	int n, n1, n2, n3, n4, n5;
	switch (Map[y][x].Name) {
		case:
		case:
			n = is_go1(x, y, cx, cy);     //走棋子n==0  //吃棋子n==1
			if (n == 0 || (n == 1 && Map[y][x].type != Map[cy][cx].type)) { //是对方棋子才能走
				zouchi(qipu, x, y, cx, cy);
				break;
			}
			break;
		case:
		case:
			n1 = is_go2(x, y, cx, cy);    //走棋子n1==0  //吃棋子n1==1
			if (n1 == 0 || (n1 == 1 && Map[y][x].type != Map[cy][cx].type)) {
				zouchi(qipu, x, y, cx, cy);
				break;
			}
			break;
		case:
		case:
			n2 = is_go3(x, y, cx, cy);    //走棋子n2==0  //吃棋子n2==1
			if (n2 == 0 || (n2 == 1 && Map[y][x].type != Map[cy][cx].type)) {
				zouchi(qipu, x, y, cx, cy);
				break;
			}
			break;
		case:
		case:
			n3 = is_go4(x, y, cx, cy);   //走棋子n3==0  //吃棋子n3==1
			if (n3 == 0 || (n3 == 1 && Map[y][x].type != Map[cy][cx].type)) {
				zouchi(qipu, x, y, cx, cy);
				break;
			}
			break;
		case:
		case:
			n4 = is_go5(x, y, cx, cy);   //对老将n4==2	//走棋子n4==0  //吃棋子n4==1
			if ((n4 == 2) || (n4 == 0) || (n4 == 1 )) {
				zouchi(qipu, x, y, cx, cy);
				break;
			}
			break;
		case:
		case:
			n5 = is_go6(x, y, cx, cy);  //走棋子n5==0  //吃棋子n5==1
			if (n5 == 0 || (n5 == 1 && Map[y][x].type != Map[cy][cx].type)) {
				zouchi(qipu, x, y, cx, cy);
				break;
			}
			break;
		case:
		case:
			n = is_go1(x, y, cx, cy);  //走棋子0 //吃棋子2
			if (n == 0 || (n == 2 && Map[y][x].type != Map[cy][cx].type)) {
				zouchi(qipu, x, y, cx, cy);
			}
			break;
		default:
			break;
	}
}
//悔棋刪链尾结点
link* deleteqipu(link * qipu) {
	link* temp = qipu;
	while (temp->next) {             //移动指针temp到qiup的最后一个节点
		temp = temp->next;
	}
	temp->prior->next = temp->next;  //temp的上一个节点的next  指向  temp的下一个节点
	free(temp);                      //释放节点temp
	return qipu;
}
//悔棋
void huiqi(link * qipu) {
	QMap ctemp;                                 //临时棋盘交换点
	link* temp = qipu;                          //临时qipu节点
	if (temp || temp->ID != -2) {               //temp不空,或不是首元结点
		while (temp->next) {
			temp = temp->next;
		}
		ctemp = Map[temp->cy][temp->cx];        //存储交换点
		Map[temp->y][temp->x] = ctemp ;
		Map[temp->y][temp->x].x = temp->x;
		Map[temp->y][temp->x].y = temp->y;
		if (1 == temp->zouchi) {
			Map[temp->cy][temp->cx] = N[top];    //从栈N[]中恢复被吃棋子
			top = popN(top);
		} else {
			Map[temp->cy][temp->cx].Name = NONE; //恢复为无棋子
			Map[temp->cy][temp->cx].ID = NONE;   //恢复为无棋子
		}
		qipu = deleteqipu(qipu);                 //恢复新棋谱
		zoudong = true;                          //已悔棋
	} else {
		printf("已悔棋到顶!");
	}
}
//开始下棋
void mouseMap(link * qipu, chessMartix * Q) {
hui:
	qipu = initqipu(qipu);
	initMap(Q);
	show();
	draw();

	gameover = false;  //true表示游戏结束,false表示游戏未结束
	flag = true;       //true表示黑棋子, false表示红棋子
	is_Select = true;  //true表示先选棋子,false表示后落棋子

	mouse_msg msg;                        //开始鼠标操作 定义鼠标名
	for (; is_run(); delay_fps(50)) {
		Gameover();                       //1.检查是否结束	获取gameover值

		while (mousemsg()) {
			msg = getmouse();             //2.获取鼠标信息
		}

		//3.点击鼠标坐标msg.x,msg.y转为棋盘坐标i,j
		int i = (int)(msg.x - BIAN + R) / GZ;       //棋子的横坐标
		int j = (int)(msg.y - BIAN + R) / GZ;       //棋子的纵坐标

		//4.gameover=true后的操作
		int A = 1;
		while (gameover == true) {
			if (((msg.x > (X(10) + GZ * 7 / 10)) && (msg.x < (X(11) + GZ * 6 / 10)))
			    && ((msg.y > Y(1) + GZ * 2 / 10) && (msg.y < Y(1) + GZ * 7 / 10))) {
				A = 2;
				drawxuanze(A);        //标注 退出
			} else if (((msg.x > (X(9) + GZ * 7 / 10)) && (msg.x < (X(10) + GZ * 6 / 10)))
			           && ((msg.y > Y(1) + GZ * 2 / 10) && (msg.y < Y(1) + GZ * 7 / 10))) {
				A = 3;
				drawxuanze(A);        //标注 再来
			} else {
				A = 1;                //取消 标注
				drawxuanze(A);
			}
			//左键点击后
			if (A == 3 && msg.is_left() && msg.is_down()) {  //选再来后
				gameover = false;       //游戏重新开始
				free(qipu);             //释放qipu
				top = -1;               //栈N回到栈顶
				goto hui;				//选再来后,回到游戏初始代码
			} else if (A == 2 && msg.is_left() && msg.is_down()) {  //选退出后
				free(qipu);             //释放qipu
				closegraph();			//选退出  关闭窗口
			} else {
				break;
			}
		}

		//5.下棋未结束时 在棋盘范围内  左键按下
		if (msg.is_left() && msg.is_down() && i < 9 && j < 10 && gameover != true) {
			//Ai();
			int x, y;                                     // 需要保存所选棋子坐标和棋子编号
			if (flag == true ) {                          // 黑棋先走
				if (is_Select == true) {                  // 选棋子
					if ( Map[j][i].Name != NONE && Map[j][i].type == BLACK) {
						xuanqizi(i, j, chessName[Map[j][i].Name], Map[j][i].type);
						y = j;
						x = i;
						is_Select = false;
						Sleep(150);
					}
				} else if (is_Select == false) {           //落棋子
					zouqizi(qipu, x, y, i, j);
					Sleep(150);
					show();
					displayqipu(qipu);
					cleardevice();
					draw();
					huaqipu(qipu);
					is_Select = true;
					if (zoudong == false) {
						flag = true;
					} else {
						flag = false;
						PlaySound(TEXT(".//image/click.wav"), NULL, SND_FILENAME | SND_ASYNC);
					}
				}
			}
			//再走紅棋
			else if (flag == false) {
				//选棋子
				if (is_Select == true) {
					if ( Map[j][i].Name != NONE && Map[j][i].type == RED) {
						xuanqizi(i, j, chessName[Map[j][i].Name], Map[j][i].type);
						y = j;
						x = i;
						is_Select = false;
						Sleep(150);
					}
				}
				//落棋子
				else if (is_Select == false) {
					zouqizi(qipu, x, y, i, j);
					Sleep(200);
					show();
					displayqipu(qipu);
					cleardevice();
					draw();
					huaqipu(qipu);
					is_Select = true;
					if (zoudong == false) {
						flag = false;
					} else {
						flag = true;
						PlaySound(TEXT(".//image/click.wav"), NULL, SND_FILENAME | SND_ASYNC);
					}
				}
			}
		}
		//6.下棋未结束时在棋盘范围内    按下右键 悔棋
		else if (msg.is_right() && msg.is_down() && i < 9 && j < 10 && gameover != true) {
			if (qipu->next != NULL) {
				huiqi(qipu);
				Sleep(200);
				show();
				displayqipu(qipu);
				cleardevice();
				draw();
				huaqipu(qipu);
				if (flag == true) {
					flag = false;
					PlaySound(TEXT(".//image/click.wav"), NULL, SND_FILENAME | SND_ASYNC);
				} else {
					flag = true;
					PlaySound(TEXT(".//image/click.wav"), NULL, SND_FILENAME | SND_ASYNC);
				}
			}
		}
	}
}
void mouseQ(link * qipu) {
	//鼠标操作前定义条件
	gameover = false;  //true表示游戏结束,false表示未游戏结束
	flag = true;       //true表示黑棋子, false表示红棋子
	is_Select = true;  //true表示先选棋子,false表示后落棋子

	//开始鼠标操作
	mouse_msg msg;
	for (; is_run(); delay_fps(20)) {
		//检查是否结束
		Gameover();
		//获取鼠标信息
		while (mousemsg()) {
			msg = getmouse();
		}
		//点击鼠标坐标msg.x,msg.y转为棋盘坐标i,j
		int i = (int)(msg.x - BIAN + R) / GZ; //棋子的横坐标
		int j = (int)(msg.y - BIAN + R) / GZ; //棋子的纵坐标

		//下棋未结束时在-------棋盘范围内-----左键按下---走棋子
		if (msg.is_left() && msg.is_down() && i < 9 && j < 10 && gameover != true) {
			//Ai();
			int x, y;                                     // 需要保存所选棋子坐标和棋子编号
			if (flag == true ) {                          // 黑棋先走
				if (is_Select == true) {                  // 选棋子
					if ( Map[j][i].Name != NONE && Map[j][i].type == BLACK) {
						xuanqizi(i, j, chessName[Map[j][i].Name], Map[j][i].type);
						y = j;
						x = i;
						is_Select = false;
						Sleep(150);
					}
				} else if (is_Select == false) {           //落棋子
					zouqizi(qipu, x, y, i, j);
					Sleep(200);
					show();
					cleardevice();
					draw();
					is_Select = true;
					if (zoudong == false) {
						flag = true;
					} else {
						flag = false;
						PlaySound(TEXT(".//image/click.wav"), NULL, SND_FILENAME | SND_ASYNC);
					}
				}
			}
			//再走紅棋
			else if (flag == false) {
				//选棋子
				if (is_Select == true) {
					for (int m = 0; m < Row; m++) {
						for (int n = 0; n < Col; n++) {
							if (Map[m][n].x == i && Map[m][n].y == j && Map[m][n].Name != NONE && Map[m][n].type == RED) {
								xuanqizi(n, m, chessName[Map[m][n].Name], Map[m][n].type);
								y = m;
								x = n;
								is_Select = false;
								Sleep(150);
							}
						}
					}
				}
				//落棋子
				else if (is_Select == false) {
					zouqizi(qipu, x, y, i, j);
					Sleep(200);
					show();
					cleardevice();
					draw();
					is_Select = true;
					if (zoudong == false) {
						flag = false;
					} else {
						flag = true;
						PlaySound(TEXT(".//image/click.wav"), NULL, SND_FILENAME | SND_ASYNC);
					}
				}
			}
		}
		//下棋未结束时在棋盘范围内右键按下 悔棋
		else if (msg.is_right() && msg.is_down() && i < 9 && j < 10 && gameover != true) {
			if (qipu->next == NULL) {
				gameover = true;
				break;
			} else {
				huiqi(qipu);
				Sleep(200);
				show();
				cleardevice();
				draw();
			}
		}
	}
}

int main() {	
	system("mode con: cols=55 lines=50");
	initgraph(weight, high);

	//棋盘矩阵Q    代替  Map[][]存储棋子
	chessMartix Q;
	Q.n = 10;
	Q.m = 9;
	Q.num = 32;

	//定义棋谱链
	link *qipu = NULL;

	//窗口界面操作
	mouseMap(qipu, &Q);
	closegraph();
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值