一、象棋介绍

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

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

中国象棋使用方形格状棋盘,圆形棋子共有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;
}

中国象棋棋子移动规则详解(Qt)相关推荐

  1. 中国象棋棋子及棋盘的绘制

    一.题目简介 本课程设计主要是使用Swing这个Java自带的图形开发工具实现中国象棋棋子及棋盘的绘制,并根据相应的象棋规则,可以设计棋谱,完成棋谱的保存和对已保存的棋谱的演示,方便现在爱棋人士对残局 ...

  2. java中国象棋兵吃棋规则_中国象棋吃子的规则

    中国象棋吃子的规则 在中国喜欢玩象棋的朋友有很多,那么对于新手来说,可能还不知道象棋如何吃子,现在小编向大家讲解一下象棋的吃子. 中国象棋吃子的规则 先从攻击力最强的棋子:车,开始讲解,车的走棋规则是 ...

  3. 教你怎么用Python和Qt5编写中国象棋AI版——规则模块

    提示:该模块用于实现规则模块 教你怎么用Python和Qt5编写中国象棋AI版--规则模块 前言 一.中国象棋大致规则? 二.各棋子规则实现思路 1.兵 注意事项 过河兵合法偏移 未过河兵合法偏移 2 ...

  4. css样式继承规则详解

    css样式继承规则详解 一.总结 一句话总结:继承而发生样式冲突时,最近祖先获胜(最近原则). 1.继承中哪些样式不会被继承? 多数边框类属性,比如象Padding(补白),Margin(边界),背景 ...

  5. Apache Rewrite 规则详解

    在开篇之前: 我想说这篇文章其实是我刚刚接触Rewrite的时候学习的文档,应属转载,但是在这里我不想写明原地址,原因是文章中大多数给出的配置命令经实验都是错误的.需要原文的可以在谷歌上搜索一下&qu ...

  6. 详解 QT 主要类 QWidget

    QWidget类是所有用户界面对象的基类,每一个窗口部件都是矩形,并且它们按Z轴顺序排列的.一个窗口部件可以被它的父窗口部件或者它前面的窗口部件盖住一部分. 先来看内容. AD: 2013云计算架构师 ...

  7. android PorterDuffXfermode ,PorterDuff.Mode 使用 以及Porter-Duff规则详解

    android PorterDuffXfermode ,PorterDuff.Mode 使用 以及Porter-Duff规则详解 1.下面的Xfermode子类可以改变这种行为: AvoidXferm ...

  8. Unity UGUI Batches合批规则详解(含源码)

    Unity UGUI Batches合批规则详解 在处理UGUI DrawCall问题的时候,我们经常遇到各式各样的问题. 问题1:在处理UGUI合批的时候,发现了一个面板父节点发生旋转,底下的UI合 ...

  9. linux下防火墙iptables用法规则详解

    linux下防火墙iptables用法规则详解 分享者: du52.com 邮件: wangaibo168@163.com 主页: http://www.du52.com linux下防火墙iptab ...

最新文章

  1. win2008WEB服务器集群实践(转)
  2. 消息中间件那些事--RabbitMQ
  3. python的stack用法_Python numpy.stack函数方法的使用
  4. 面向对象初调用:foolish 电梯
  5. 12.14-Linux系统优化
  6. 关于vim的误删除经历
  7. 循环中的continue功能
  8. GBT19668.3-2007 电子设备机房系统工程监理规范
  9. arduino 可以用c_lt;开源项目gt;Arduino+STM32+SIM868 用一天创造一款可以定位的GPRS无线开关...
  10. MFC 进行界面设计与编程
  11. 用计算机求回归,鲜为人知的用途,回归分析用计算器就能做!
  12. 修改注册表阻止Office XP发送错误报告
  13. html网页图片下方空隙太大,div+css排版图片IMG下边界有空隙
  14. C++动态壁纸软件的开发(含源文件)
  15. design/sourcecode/课堂笔记designPrinciples
  16. Mac下的winscp替代者 FileZilla
  17. 理想低通滤波器、Butterworth滤波器和高斯滤波器(matlab)
  18. How add nic driver to initrd
  19. SQL函数lpad()以及rpad()的用法
  20. visibility:属性

热门文章

  1. Mendeley文献导入与管理
  2. 置信概率的含义如何?与置信区间有何关系?
  3. 曹参想念他的永中“小毛头‘
  4. Vue2.0饿了吗的实践-header组件的实践
  5. 手把手教学制作静态库和动态库
  6. Centos7.x设置重启X Window的组合键
  7. 2017广东高考作文题出炉:选择两三个关键词
  8. tiktok直播显示服务器升级,tiktok直播显示服务器升级
  9. java布局器嵌套_java swing布局嵌套
  10. 快速理解决策树 bootstrap,bagging,boosting,online boosting-五个概念