整体架构如上
1.很直观地去看这个中国象棋的界面,数一下它有多少行和多少列.
10行,9列:要注意这里数的是安放象棋的位置,有10行9列
这里我们首先想到的必然是二维数组,每一个行列交叉的点都设置成二维数组a[i][j]这样的格式,以此来确定棋盘上面每一个棋子的位置和走向.
我们把上面安放棋子的二维数组定义成一个地图,也就是map[i][j]的格式,但同时要注意,每一个象棋棋子都有行,列,颜色,是否过河和名称(也就是什么棋子)几种定义区分.
那么这里我们就需要把棋子定义成一个结构.如下:
- struct Chesscoordinate//棋子综合信息
- {
- int x;
- int y;
- DWORD type; //颜色
- bool river;//是否过河
- int id;
- };
当定义了棋子综合信息,我们是不是需要每一个信息都拓展一下?
x代表的是在棋盘上面的列,也就是竖行,y代表的是棋子在棋盘上面的行,也就是横线,而type代表的棋子的颜色,棋子颜色可以分为黑色和红色两种;river设置成bool型的,只需要判断棋子是否过河就可以了.最后id定义的是棋子上面的名称,比如将,帅等.
接下来我们就来VS当中进行棋子的程序定义拓展:
- #define distance 35//窗口线与棋盘边界线的距离
- #define longth 65//棋盘方格的长
- #define high 61//棋盘方格的宽
distance longth 和high我们都把其设置成宏,这个就要回溯到棋盘上面,把棋盘假设成一个xy的二维坐标,那么要定义每一个棋子的位置,或者说是每一行与每一列的交叉点,就要用到上面三个宏定义.
比如左上角第一个棋子的坐标可以表示为:
map[0][0].x=distance;
map[0][0].y=distance
而第一行第二个棋子的坐标可以表示为:
map[1][0].x=distance+longth;
map[1][0].y=distance
依次类推......
- int xx(int a)//数组下标转换成坐标
- {
- a = distance + longth * a;
- return a;
- }
- int yy(int a)
- {
- a = distance + high * a;
- return a;
- }
我们可以推断出每一个棋子的坐标,都可以通过上面几个宏定义以及棋子的实际行列表示出来,
- 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[] = { "車","馬","象","士","将","炮","卒","车","马","相","仕","帥","砲","兵", };
这里我们把棋子的id设置成一个联合结构数组,因为里面的棋子的id都基本不同,同时我们考虑到了棋子要进行运动,把棋子的开始状态设置为BEGIN
而新建一个move的结构,表示鼠标选中棋子的基本信息.begin的行列和结束的行列和运行状态.
最后回到棋子id上面,我们是不是需要把这些id都设置到棋子或者棋盘上面啊,采用常量字符数组的形式,把棋盘上面所有的棋子都表示出来.
而把刚才的map[i][j]二维数组同样定义成一个二维结构数组.如下:
- struct Chesscoordinate map[9][10];//坐标
- struct Chesscoordinate AImap[9][10];//坐标
同时,我们设置了AImap[i][j]的二维结构数组,看看是否下面在进行棋子移动的时候,我们会用到.
这里i=9,j=10是根据我们上面看中国象棋棋盘得到的数据.
2.我们要开始加载图片信息了,把我们已经有的棋盘素材放在同文件下面,然后采用下面程序,就可以在窗口当中显示出中国棋盘的背景图.
- void begining()
- {
- loadimage(&img, "D:/program/Project3-chess successful/1.png");
- initgraph(img.getwidth(), img.getheight(), 1); //初始化图形系统
- putimage(0, 0, &img);//输出开始界面;
至于,loadimage()和initgraph()函数以及putimage()函数三者的基本理解和解释,建议去搜索,都有比较详细的解释.这里我们解释一下initgraph()函数的基本含义:
这个函数用于初始化绘图环境。
- HWND initgraph(
- int width,
- int height,
- int flag = NULL
- );
参数:
width 绘图环境的宽度。
height 绘图环境的高度。
flag 绘图环境的样式,默认为 NULL。
上面程序的基本思路也就不言而喻:先加载或者找到我们素材的地址,然后定义出素材的宽和长度,然后再输出这个棋盘背景.
当输出完背景之后,我们是不是要先把所有的棋子放在初始位置,也就是初始化棋盘?
- void coord()//棋子信息赋值
- {
- loadimage(&img, "D:/program/Project3-chess successful/1.png");
- 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;
- }
- }
- }
-
- }
看上述程序:
首先先加载出棋盘背景,然后把棋盘上面行和列交叉的位置都设置为SPACE,可以理解为初始化棋盘.然后如果j<=4,也就是楚河的一侧,我们定义棋子type全部都为黑色,而棋子的id要根据行列的位置来确定,首先看第一行,前5列数据,是不是应该是"車,馬,象,士,将"而后四列数据,是不是应该是前面去除将的反序,而观察一下,如果把前面定义成i列,后面对应相等的字符则是8-i列.那么我们就定义完了第一行的数据.
而炮和兵的数据,以及红方的数据是不是同上述思路一样.
然后就开始定义每一个棋子初始化的状态,回溯到棋子的基本信息结构当中,有x,y,river,type和id,我们要依次对其进行定义,
注意在初始状态的时候,棋子的river都为false,因为都没有过楚河
定义完棋子的位置,那么剩下没有棋子的位置,我们是不是要把刚开始初始化的状态都修改为棋盘的背景颜色啊.上述定义完,再次输出棋盘
- void qiban()
- {
- loadimage(&img, "D:/program/Project3-chess successful/1.png");
- initgraph(img.getwidth(), img.getheight(), 1);
- putimage(0, 0, &img);//输出棋盘
- }
这个时候就已经初始化了中国象棋的棋盘.
接下来是不是要把每一个棋子都定义到棋盘上面.开始绘画棋子
- 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]);
-
- }
- }
- }
-
- }
如果上面棋盘行列之间的id不是SPACE,那自然就是我们定义的棋子应该安置的位置.从第0行第0列开始,依次进行定义:
画一个棋子,两个圆环,其颜色要画成背景颜色,而棋子上面的文本颜色要根据实际行列定义的type,设置成黑色和红色,
最后便是采用outtextxy()把每一个棋子的字符输入进行.注意此处根据棋盘x和y的地址均减13,是根据实际调试来进行,并不是确定常量.
写到这里,是不是就把棋子和棋盘都初始化好了?yes,of course.
3.棋盘棋子都初始化好了,那么接下来我们是不是就可以开始移动棋盘上面的棋子,进行下棋了?
这里有一个有意思的思考:我刚开始认为吃掉棋子和走到空白的地方是两种不同的情况,后面仔细思考了一下,是同一状态,只需要把原来的修改为结束的就可以了,而原来的只需要位置只需要修改颜色和id为空也就没了,不管他end地址有没有棋子.
- 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;
-
-
- }
- int xx(int a)//数组下标转换成坐标
- {
- a = distance + longth * a;
- return a;
- }
- int yy(int a)
- {
- a = distance + high * a;
- return a;
- }
把[a][b]位置的棋子信息,全部给了[c][d]位置处的棋子,而[a][b]棋子此处的信息要记得修改id和type,id设置为空,而颜色设置成背景颜色.而xx(c),yy(d)就成了棋子移动到下一个点的坐标
- 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);
-
-
- }
-
-
- }
-
- }
-
- }
上面这一段我其实有一点不清晰,我所理解的应该是定义了两个状态,如果状态是开始的时候,那状态改为结束,然后把第一次点击的数据给了开始的数据,如果状态是结束,把状态修改为开始,把第一次点击的数据给了结束的坐标.
关键:
- intbeginrow = round(beginrow);
- intbeginrol = round(beginrol);
判断输赢:
- 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 %d\n", blackgeneral, redgeneral);
-
- if (blackgeneral == 0)//红方胜
- {
- return 0;
-
- }
- else if (redgeneral == 0)//黑方胜
- {
-
- return 1;
- }
- else//打平
- {
- return 2;
- }
-
-
- }
给将和帅都定义了初始值,相当于如果将死了,那就是帅赢,相反同理,而如果两者都存在,也就是1+1,那自然就是平手,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("%d\n", 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("%d\n", 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("max\min:(%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("xx\yy:(%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;
- }
上述全都是bool型,用以表示判断是否正确就行
接下来是行棋子,如果遵守规则,也就是上面的bool输出true,则移动,否则输出"你不能这样做!"
- 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();
- /*这个函数用于开始批量绘图。执行后
- 任何绘图操作都将暂时不输出到绘图窗口上,直到执行 FlushBatchDraw 或 EndBatchDraw 才将之前的绘图输出。*/
- //运行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;
- }
总代码:
- #include<stdio.h>
- #include<graphics.h>
- #include<math.h>
- 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, "D:/program/Project3-chess successful/1.png");
- initgraph(img.getwidth(), img.getheight(), 1); //初始化图形系统
- putimage(0, 0, &img);//输出开始界面;
-
- }
- void qiban()
- {
- loadimage(&img, "D:/program/Project3-chess successful/1.png");
- initgraph(img.getwidth(), img.getheight(), 1);
- putimage(0, 0, &img);//输出棋盘
- }
- void coord()//棋子信息赋值
- {
- loadimage(&img, "D:/program/Project3-chess successful/1.png");
- 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 %d\n", 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("%d\n", 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("%d\n", 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("max\min:(%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("xx\yy:(%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();
- /*这个函数用于开始批量绘图。执行后
- 任何绘图操作都将暂时不输出到绘图窗口上,直到执行 FlushBatchDraw 或 EndBatchDraw 才将之前的绘图输出。*/
- //运行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;
- }
总代码参考于: