一、主要目标:
1.1:鼠标控制。
1.2:各棋子按照象棋规则移动
1.3:判断双方胜负
注:本设计使用vs-2017运行。需要下载graphics.h库。
二、基本流程
2.1 棋牌展示
直接输出棋盘背景图片,包含方格线、“楚河”、“汉界”等,代码如下:
loadimage(&img, "C:/Users/ASUS/Desktop/shess/5.jpg");
putimage(0, 0, &img);//输出棋盘
该地址下放如图所示2.1所示图片充当背景。
图2.1 棋盘背景图片
2.3.2 棋子展示
按照象棋棋子的摆法,在指定坐标出画出棋子(先画圆圈,再写字,每个棋子都如此)。
2.3.3 各棋子子移动
俥,马,象,士,炮,将,兵分别写移动规则(根据起始坐标和目的坐标判断是否可以移动)。
2.3.4 判断胜负
棋盘信息没改变一次就扫描一次棋盘,如果一方的将被覆盖(被对方所吃),则输出另一方获胜。游戏结束。
完整代码:
#include#include #include void execute(int a, int b, int c, int d); bool jiang(int a, int b, int c, int d); bool pao(int a, int b, int c, int d); bool ma(int a, int b, int c, int d); IMAGE img; #define distance 35//窗口线与棋盘边界线的距离 #define longth 65//棋盘方格的长 #define high 61//棋盘方格的宽 struct movecoordinate { long x; long y; }; struct Chesscoordinate//棋子综合信息 { int x; int y; DWORD type; //颜色 bool river;//是否过河 int id; }; enum pieces { SPACE = -1, 車, 馬, 象, 士, 将, 炮, 卒, 车, 马, 相, 仕, 帥, 砲, 兵, BEGIN, END, }; enum pieces redchess[] = { 車,馬,象,士,将,炮,卒, }; enum pieces blackchess[] = { 车,马,相,仕,帥,砲,兵, }; enum pieces state = BEGIN; struct move { //鼠标选中的棋子 int beginx; int beginy; int endx; int endy; int state; }moving = { -1,-1,-1,-1,BEGIN }; const char* chessname[] = { "車","馬","象","士","将","炮","卒","车","马","相","仕","帥","砲","兵", }; struct Chesscoordinate map[9][10];//坐标 struct Chesscoordinate AImap[9][10];//坐标 movecoordinate begin = { -1,-1 }, end = { -1,-1 }; int xx(int a)//数组下标转换成坐标 { a = distance + longth * a; return a; } int yy(int a) { a = distance + high * a; return a; } void begining() { loadimage(&img, "C:/Users/ASUS/Desktop/shess/66.jpg"); initgraph(img.getwidth(), img.getheight(), 1); putimage(0, 0, &img);//输出开始界面; } void qiban() { loadimage(&img, "C:/Users/ASUS/Desktop/shess/5.jpg"); initgraph(img.getwidth(), img.getheight(), 1); putimage(0, 0, &img);//输出棋盘 } void coord()//棋子信息赋值 { loadimage(&img, "C:/Users/ASUS/Desktop/shess/5.jpg"); putimage(0, 0, &img);//输出棋盘 for (int i = 0; i <= 8; i++) { for (int j = 0; j <= 9; j++)//遍历二维数组 { enum pieces chessid = SPACE;//先把全部位置的id赋值为SAPCE DWORD chesstype;//定义颜色中间变量 if (j <= 4) { chesstype = BLACK;//黑方 if (j == 0) { if (i <= 4) { chessid = blackchess[i];// } else { chessid = blackchess[8 - i]; } } if (j == 2 && (i == 1 || i == 7)) { chessid = blackchess[5]; } if (j == 3 && (i == 0 || i == 2 || i == 4 || i == 4 || i == 6 || i == 8)) { chessid = blackchess[6]; } } else { chesstype = RED;//红方 if (j == 6 && (i == 0 || i == 2 || i == 4 || i == 6 || i == 8)) { chessid = redchess[6]; } if (j == 7 && (i == 1 || i == 7)) { chessid = redchess[5]; } if (j == 9) { if (i <= 4) { chessid = redchess[i]; } else { chessid = redchess[8 - i]; } } }//依次赋值 map[i][j].id = chessid; map[i][j].river = false; map[i][j].type = chesstype; map[i][j].x = distance + longth * i; map[i][j].y = distance + high * j; } } for (int i = 0; i <= 8; i++) { for (int j = 0; j <= 9; j++) { if (map[i][j].id == SPACE) { map[i][j].type = YELLOW; } } } } void getbackground() //画棋子 { int x_start, y_start; x_start = distance; y_start = distance; settextstyle(30, 0, "黑体");//棋子大小颜色 setbkmode(0); for (int i = 0; i <= 8; i++) { for (int j = 0; j <= 9; j++) { if (map[i][j].id != SPACE)//在棋盘上输出 { setfillcolor(RGB(253, 216, 161)); // setlinestyle(BLACK); settextcolor(map[i][j].type); fillcircle(map[i][j].x, map[i][j].y, 24); fillcircle(map[i][j].x, map[i][j].y, 18); outtextxy(map[i][j].x - 13, map[i][j].y - 13, chessname[map[i][j].id]); } } } } void movechess(int a, int b, int c, int d)//移动棋子,改变其坐标 { map[c][d].id = map[a][b].id; map[c][d].river = map[a][b].river; map[c][d].type = map[a][b].type; map[c][d].x = xx(c); map[c][d].y = yy(d); map[a][b].id = SPACE; map[a][b].type = YELLOW; } void MouseControl()//获取鼠标点击信息并完响应 { //getbackground(); if (MouseHit()) { float beginrow, beginrol, endrow, endrol;//第一次按下时的坐标 int intbeginrow, intbeginrol, intendrow, intendrol;//第二次按下时的坐标 MOUSEMSG msg = GetMouseMsg(); if (msg.uMsg == WM_LBUTTONDOWN) { //获取鼠标点击的数组的下标 // printf("(%d,%d)", msg.x, msg.y); beginrow = (float)(msg.x - distance) / longth; beginrol = (float)(msg.y - distance) / high; intbeginrow = round(beginrow); intbeginrol = round(beginrol); if (moving.state == BEGIN) { moving.state = END; moving.beginx = intbeginrow; moving.beginy = intbeginrol; // printf("(%d,%d) n", moving.beginx, moving.beginy); } else if (moving.state == END) { moving.state = BEGIN; moving.endx = intbeginrow; moving.endy = intbeginrol; execute(moving.beginx, moving.beginy, moving.endx, moving.endy); } } } } int win() { int redgeneral = 0; int blackgeneral = 0; for (int i = 0; i <= 8; i++) { for (int j = 0; j <= 9; j++) { if (map[i][j].id == blackchess[4]) { blackgeneral++; } else if (map[i][j].id == redchess[4]) { redgeneral++; } else { blackgeneral = blackgeneral; redgeneral = redgeneral; } } } //printf("%d %dn", blackgeneral, redgeneral); if (blackgeneral == 0) { return 0; } else if (redgeneral == 0) { return 1; } else { return 2; } } bool jiang(int a, int b, int c, int d)//判断是否只移动了一格(将军、兵的规则) { float h; h = sqrt(abs(d - b)*abs(d - b) + abs(c - a)*abs(c - a)); if (b < 4 && c > 2 && c < 6 && d < 3) { if (h == 1 && map[c][d].type != map[a][b].type) return true; else return false; } if (b > 4 && c > 2 && c < 6 && d >6) { if (h == 1 && map[c][d].type != map[a][b].type) return true; else return false; } else { return false; } } bool bing(int a, int b, int c, int d) { float h; h = sqrt(abs(d - b)*abs(d - b) + abs(c - a)*abs(c - a)); if (map[a][b].type == BLACK) { if (map[a][b].river == false) { if (d == b + 1 && h == 1 && map[c][d].type != map[a][b].type) { return true; } else { return false; } } else { if (d >= b && h == 1 && map[c][d].type != map[a][b].type) { return true; } else { return false; } } } else if (map[a][b].type == RED) { if (map[a][b].river == false) { if (d == b - 1 && h == 1 && map[c][d].type != map[a][b].type) { return true; } else { return false; } } else { if (d <= b && h == 1 && map[c][d].type != map[a][b].type) { return true; } else { return false; } } } else { return false; } } bool pao(int a, int b, int c, int d)//炮的移动 { if (c == a && d != b) { int time = 0; int max = d > b ? d : b; int min = b < d ? b : d; for (int i = min; i <= max; i++) { if (map[c][i].id != SPACE) { time++; } } // printf("%dn", time); if (map[c][d].id == SPACE) { if (time == 1) return true; else return false; } if (map[c][d].id != SPACE) { if (time != 3) { return false; } else { if (map[c][d].type == map[a][b].type) { return false; } else { return true; } } } } else if (d == b && c != a) { int time = 0; int max = a > c ? a : c; int min = c < a ? c : a; for (int i = min; i <= max; i++) { if (map[i][d].id != SPACE) { time++; } } // printf("%dn", time); if (map[c][d].id == SPACE) { if (time == 1) return true; else return false; } if (map[c][d].id != SPACE) { if (time != 3) { return false; } else { if (map[c][d].type == map[a][b].type) { return false; } else { return true; } } } } else { return false; } } bool che(int a, int b, int c, int d) { if (c == a && d != b)//是否为直线 { int time = 0; int max = d > b ? d : b; int min = b < d ? b : d; for (int i = min; i <= max; i++)//遍历路径 { if (map[c][i].id != SPACE) { time++; } } // printf("%d", time); if (time == 1)//车移动不吃棋子 { return true; } if (time == 2)//车移动并且吃目的坐标的棋子 { if (map[c][d].type == map[a][b].type)//如果是目的坐标是自己的棋子,则返回false { return false; } if (map[c][d].type == YELLOW) { return false; } else { return true; } } else { return false; } } else if (d == b && c != a) { int time = 0; int max = c > a ? c : a; int min = a < c ? a : c; for (int i = min; i <= max; i++)//遍历路径 { if (map[i][d].id != SPACE) { time++; } } // printf("%d", time); if (time == 1)//车是否车跳棋 { return true; } else if (time == 2) { if (map[c][d].type == map[a][b].type) { return false; } if (map[c][d].type == YELLOW) { return false; } else { return true; } } else { return false; } } else { return 0; } } bool ma(int a, int b, int c, int d) { float h; h = sqrt(abs(d - b)*abs(d - b) + abs(c - a)*abs(c - a)); // printf("%f", h); if (h <= 2 || h >= 2.5)//根号8=2.8.根号5=2.2 { // printf("太远了!n"); return false; } else { int xx, yy, max, min;//关键点的坐标和中间值 max = abs(d - b) > abs(c - a) ? abs(d - b) : abs(c - a); min = abs(c - a) < abs(d - b) ? abs(c - a) : abs(d - b); //printf("maxmin:(%d,%d)", max, min); if (max == abs(d - b)) { yy = b + (d - b) / 2; xx = a; } else { xx = a + (c - a) / 2; yy = b; } // printf("xxyy:(%d,%d)n", xx, yy); if (map[xx][yy].id == SPACE) { if (map[c][d].type != map[a][b].type) { // printf("目的坐标(%d,%d)n", c, d); // printf("那是你自己的棋子!n"); return true; } else { // printf("那是你的棋子!n"); return false; } } else { // printf("关键位置有棋子!n"); return false; } } } bool xiang(int a, int b, int c, int d) { float h; h = sqrt(abs(d - b)*abs(d - b) + abs(c - a)*abs(c - a)); if (b <= 4) { if (d > 4) { return false; } else { if (h<2.4 || h>2.9) { return false; } else { int xx = (a + c) / 2; int yy = (b + d) / 2; if (map[xx][yy].id == SPACE) { if (map[c][d].type == map[a][b].type) { return false; } else { return true; } } else { return false; } } } } else { if (d < 5) { return false; } else { if (h<2.4 || h>2.9) { return false; } else { int xx = (a + c) / 2; int yy = (b + d) / 2; if (map[xx][yy].id == SPACE) { if (map[c][d].type == map[a][b].type) { return false; } else { return true; } } else { return false; } } } } } bool shi(int a, int b, int c, int d) { float h = sqrt(abs(d - b)*abs(d - b) + abs(c - a)*abs(c - a)); // printf("%f", h) if (b < 5) { if (c >= 3 && c <= 5 && d <= 2) { if (1.2 < h &&h < 1.5) { if (map[c][d].type != map[a][b].type) return true; else return false; } else { return false; } } else { return false; } } else if (b > 5) { if (c >= 3 && c <= 5 && d >= 7) { if (1.2 < h &&h < 1.5) { if (map[c][d].type != map[a][b].type) return true; else return false; } else { return false; } } else { return false; } } else return false; } void execute(int a, int b, int c, int d)//行棋 { if (map[a][b].id == blackchess[4])//黑方将 { if (jiang(a, b, c, d)) { movechess(a, b, c, d); } else { printf("你不能这样做n"); } } else if (map[a][b].id == redchess[4])//红方将 { if (jiang(a, b, c, d)) { movechess(a, b, c, d); } else { printf("你不能这样做!n"); } } else if (map[a][b].id == blackchess[6])//黑方兵 { if (map[a][b].river == false) { if (bing(a, b, c, d)) { movechess(a, b, c, d); if (d > 4) { map[c][d].river = true; } } else { printf("你不可以这样做!n"); } } else { if (bing(a, b, c, d) && d >= b) { movechess(a, b, c, d); } else { printf("你不可以这样做n"); } } } else if (map[a][b].id == redchess[6])//红方兵 { if (map[a][b].river == false) { if (bing(a, b, c, d)) { movechess(a, b, c, d); if (d < 5) { map[c][d].river = true; } } else { printf("你不可以这样做!n"); } } else { if (bing(a, b, c, d) && d <= b) { movechess(a, b, c, d); } else { printf("你不可以这样做!n"); } } } else if (map[a][b].id == blackchess[5] || map[a][b].id == redchess[5]) { if (pao(a, b, c, d)) { movechess(a, b, c, d); } else { printf("你不能这样做!n"); } } else if (map[a][b].id == blackchess[0] || map[a][b].id == redchess[0]) { if (che(a, b, c, d)) { movechess(a, b, c, d); } else { printf("你不可以这样做!n"); } } else if (map[a][b].id == blackchess[1] || map[a][b].id == redchess[1]) { if (ma(a, b, c, d)) { movechess(a, b, c, d); } else { printf("你不能这样做!n"); } } else if (map[a][b].id == blackchess[2] || map[a][b].id == redchess[2]) { if (xiang(a, b, c, d)) { movechess(a, b, c, d); } else printf("你不能这样做!n"); } else if (map[a][b].id == blackchess[3]) { if (shi(a, b, c, d)) { movechess(a, b, c, d); } else printf("你不能这样做!"); } else if (map[a][b].id == redchess[3]) { if (shi(a, b, c, d)) { movechess(a, b, c, d); } else printf("你不能这样做!"); } } int main() { begining(); while (1) { coord();//输出棋盘 win(); BeginBatchDraw(); while (win() == 2) { win(); putimage(0, 0, &img); getbackground();//输出棋子 MouseControl();//鼠标更改数据 FlushBatchDraw(); } putimage(0, 0, &img); getbackground();//输出棋子 MouseControl();//鼠标更改数据 FlushBatchDraw(); if (win() == 0) { printf("红方胜!n"); } else if (win() == 1) { printf("黑方胜!n"); } } getchar(); return 0; }
注意:由于棋子是根据所选棋盘图片的大小、在指定位置画棋子。棋盘的不一样会导致棋子位置不正确。读者可直接将该棋盘复制,将图片修改成和我一样的比例,如图2.2.
图2.2 棋盘背景图片大小
读者也可以自己选择背景图片,根据图片大小,更改该代码宏定义处的distance、longth、high的值,保证棋子落在正确的位置上。另外包含人机部分的代码已上传到我的另一篇博客,请需要的自提。



