600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > 中国象棋棋子移动规则详解(Qt)

中国象棋棋子移动规则详解(Qt)

时间:2018-07-10 16:02:17

相关推荐

中国象棋棋子移动规则详解(Qt)

一、象棋介绍

中国象棋是起源于中国的一种棋,属于二人对抗性游戏的一种,在中国有着悠久的历史。由于用具简单,趣味性强,成为流行极为广泛的棋艺活动。

中国象棋是中国棋文化,也是中华民族的文化瑰宝,它源远流长,趣味浓厚,基本规则简明易懂。中国象棋在中国的群众基础远远超过围棋,是普及最广的棋类项目,中国象棋已流传到十几个国家和地区。

中国象棋使用方形格状棋盘,圆形棋子共有32个,红黑二色各有16个棋子,摆放和活动在交叉点上。双方交替行棋,先把对方的将(帅)“将死”的一方获胜。

二、说明

2.1 棋盘说明

棋子活动的场所,叫作“棋盘”。在方形的平面上,由九条平行的竖线和十条平行的横线相交组成,共有九十个交叉点,棋子就摆在交叉点上。中间部分,也就是棋盘的第五,第六两横线之间未画竖线的空白地带称为“河界”。两端的中间,也就是两端第四条到第六条竖线之间的正方形部位,以斜交叉线构成“米”字方格的地方,叫作“九宫”(它恰好有九个交叉点)。整个棋盘以“河界”分为相等的两部分。

2.2 结构说明

Chessman表示当前棋子的所在为,x,y表示即将移动到该点的位置,范围true表示可以移动,返回false表示不能移动。

2.3 将(帅)移动说明

红方为“帅”,黑方为“将”。帅和将是棋中的首脑,是双方竭力争夺的目标。

它只能在“九宫”之内活动,可上可下,可左可右,每次走动只能按竖线或横线走动一格。帅与将不能在同一直线上直接对面,否则走方判负。

由于将(帅)每次只能移动一格无论上下都能移动,因此其横纵坐标的差值的绝对值肯定为1。只要限制其移动范围在米字格中就可以了。

红方帅判断代码如下,红方在下:

bool MainWindow::MoveJiangR(Chessman *chess, int x, int y){if (x >= 3 && x <= 5 && y >= 7) {if ((abs(chess->getX() - x) + abs(chess->getY() - y)) == 1) {return true;}}return false;}

黑方帅判断代码如下,黑方在上:

bool MainWindow::MoveJiangB(Chessman *chess, int x, int y){if (x >= 3 && x <= 5 && y <= 2) {if ((abs(chess->getX() - x) + abs(chess->getY() - y)) == 1) {return true;}}return false;}

2.3 士移动说明

红方为“仕”,黑方为“士”。它也只能在九宫内走动。它的行棋路径只能是九宫内的斜线。士一次只能走一个斜格。

由于士只能斜走,因此在横纵坐标中必须移动一个,因此判断横坐标的差值绝对值等于1,同时纵坐标的绝对值也必须等于1。还需要判断其移动范围即可。

红方移动代码如下:

bool MainWindow::MoveShiR(Chessman *chess, int x, int y){bool res = false;if (abs(chess->getX() - x) == 1 && abs(chess->getY() - y) == 1 && x >= 3 &&x <= 5 && y >= 7) {res = true;}return res;}

黑方移动代码如下:

bool MainWindow::MoveShiB(Chessman *chess, int x, int y){bool res = false;if (abs(chess->getX() - x) == 1 && abs(chess->getY() - y) == 1 && x >= 3 &&x <= 5 && y <= 3) {res = true;}return res;}

2.4 象移动说明

红方为“相”,黑方为“象”。它的走法是每次循对角线走两格,俗称“象飞田”。相(象)的活动范围限于“河界”以内的本方阵地,不能过河,且如果它走的“田”字中央有一个棋子,就不能走,俗称“塞象眼”。

象的移动和士很相似,但是有一个不同的就是象眼,只需要判断其原位置和移动后位置的中间是否有棋子就能判断其是否可以移动。

红方移动代码如下:

bool MainWindow::MoveXiangR(Chessman *chess, int x, int y){bool res = false;if (abs(chess->getX() - x) == 2 && 2 == abs(chess->getY() - y) && y >= 5) {res = true;// 塞象眼Chessman *tempchess = nullptr;int tempx = (chess->getX() + x) / 2;int tempy = (chess->getY() + y) / 2;tempchess = getChess(tempx, tempy);if (tempchess != nullptr) {res = false;}}return res;}

黑方移动代码如下:

bool MainWindow::MoveXiangB(Chessman *chess, int x, int y){bool res = false;if (abs(chess->getX() - x) == 2 && 2 == abs(chess->getY() - y) && y <= 4) {res = true;Chessman *tempchess = nullptr;int tempx = (chess->getX() + x) / 2;int tempy = (chess->getY() + y) / 2;tempchess = getChess(tempx, tempy);if (tempchess != nullptr) {res = false;}}return res;}

2.4 车移动说明

车在象棋中威力最大,无论横线、竖线均可行走,只要无子阻拦,步数不受限制。俗称“车行直路”。因此,一车最多可以控制十七个点,故有“一车十子寒”之称。

​ 车的移动需要分为横向移动和纵向移动两种情况,我的方案是统计在车的移动路径中的棋子总数如果小于等于1,那么就可以移动。(相同棋子被选择的情况在该判断前就已经完成,所以这里无需考虑相同棋子的情况。)由于红黑双方的棋子都没有特殊限制因此车的代码红黑双方是一致的。

移动代码如下:

bool MainWindow::MoveChe(Chessman *chess, int x, int y){bool res = false;// 记录车路劲上的障碍物的数量。int c = 0;// 情况一,横向移动,判断车在移动时经过的棋子有多少个,若果大于1个那么就不移动。// 如果等于1个那么需要需要判断是否与车的角色相同,相同不移动,不同移动if (chess->getX() == x && chess->getY() != y) {int minY = 0, maxY = 0;if (y > chess->getY()) {minY = chess->getY();maxY = y;} else if (y < chess->getY()) {minY = y;maxY = chess->getY();}for (int i = minY; i <= maxY; i++) {Chessman *tempchess = getChess(x, i);if (tempchess != nullptr && chess->getY() != i) {c++;}}}// 情况二,纵向移动判断if (chess->getY() == y && chess->getX() != x) {int minX = 0, maxX = 0;if (x > chess->getX()) {minX = chess->getX();maxX = x;} else if (x < chess->getX()) {minX = x;maxX = chess->getX();}for (int i = minX; i <= maxX; i++) {Chessman *tempchess = getChess(i, y);if (tempchess != nullptr && chess->getX() != i) {c++;}}}if (c <= 1) {res = true;}return res;}

2.5 炮的移动说明

炮在不吃子的时候,走动与车完全相同,但炮在吃子时,必须跳过一个棋子,我方的和敌方的都可以,俗称“炮打隔子”、“翻山”。

该判断方法和车相同,统计原位置和目标位置的棋子总数,如果等于0或者等于2都可以移动。(相同棋子被选择的情况在该判断前就已经完成,所以这里无需考虑相同棋子的情况。)

bool MainWindow::MovePao(Chessman *chess, int x, int y){int res = false;int c = 0;if (chess->getX() == x && chess->getY() != y) {int minY = 0, maxY = 0;if (y > chess->getY()) {minY = chess->getY();maxY = y;} else if (y < chess->getY()) {minY = y;maxY = chess->getY();}for (int i = minY; i <= maxY; i++) {Chessman *tempchess = getChess(x, i);if (tempchess != nullptr && chess->getY() != i) {c++;}}}if (chess->getY() == y && chess->getX() != x) {int minX = 0, maxX = 0;if (x > chess->getX()) {minX = chess->getX();maxX = x;} else if (x < chess->getX()) {minX = x;maxX = chess->getX();}for (int i = minX; i <= maxX; i++) {Chessman *tempchess = getChess(i, y);if (tempchess != nullptr && chess->getX() != i) {c++;}}}if (c == 0) {res = true;} else if (c == 2) {res = true;}return res;}

2.6 马的移动说明

马走动的方法是一直一斜,即先横着或直着走一格,然后再斜着走一个对角线,俗称“马走日”。马一次可走的选择点可以达到四周的八个点,故有“八面威风”之说。如果在要去的方向有别的棋子挡住,马就无法走过去,俗称“蹩马腿”。

我们方案是先过滤8个可以移动的位置。然后看是否蹩马腿 ,如果蹩马腿那么就不让其移动。

bool MainWindow::MoveMa(Chessman *chess, int x, int y){bool res = false;if ((abs(chess->getX() - x) + abs(chess->getY() - y)) == 3) {res = true;} else {return false;}// 蹩马腿判断if (abs(chess->getX() - x) == 2) {if (x > chess->getX()) {Chessman *temp = getChess(chess->getX() + 1, chess->getY());if (temp != nullptr) {res = false;}} else {Chessman *temp = getChess(chess->getX() - 1, chess->getY());if (temp != nullptr) {res = false;}}} else if (abs(chess->getY() - y) == 2) {if (y > chess->getY()) {Chessman *temp = getChess(chess->getX(), chess->getY() + 1);if (temp != nullptr) {res = false;}} else {Chessman *temp = getChess(chess->getX(), chess->getY() - 1);if (temp != nullptr) {res = false;}}}

2.7兵/卒移动说明

红方为“兵”,黑方为“卒”。

兵(卒)只能向前走,不能后退,在未过河前,不能横走。过河以后还可左、右移动,但也只能一次一步,即使这样,兵(卒)的威力也大大增强,故有“小卒过河顶大车”之说。

bool MainWindow::MoveBindR(Chessman *chess, int x, int y){bool res = false;if (y > 4) {if (chess->getY() == y + 1 && x == chess->getX()) {res = true;}} else {if (chess->getX() == x && chess->getY() == y + 1) {res = true;}if ((chess->getX() == x + 1 || chess->getX() == x - 1) &&chess->getY() == y) {res = true;}}return res;}bool MainWindow::MoveBindB(Chessman *chess, int x, int y){bool res = false;if (y < 5) {// 没有过河前,只能向前走if (chess->getY() == y - 1 && x == chess->getX()) {res = true;}} else {if (chess->getX() == x && chess->getY() == y - 1) {res = true;}if ((chess->getX() == x + 1 || chess->getX() == x - 1) &&chess->getY() == y) {res = true;}}return res;}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。