有了前两篇的象棋棋盘和象棋棋子的铺垫,那么基本的象棋的雏形就出来,接下来要完善各个棋子行走的规则就可以让棋子移动起来,在贴代码之前,让我们回想一下象棋棋子的行走规则吧!在象棋中:士走斜线,象走田字格,马走日子格,車和炮都能直接移动,兵只能前进,不能后退,过河不能左右移动,过河后可以移动,将只能在规定的方格中行走。这是象棋棋子行走规则的基本规则,下面看看详细的移动步骤实现。

在 chessarea.h 头文件中添加相关函数声明:

   // 判断一颗棋子能不能移动bool canMove(int moveid, int killid, int x, int y);// 判断士能不能移动bool canMoveSHI(int moveid,int killid, int x,int y);// 判断兵能不能移动bool canMoveBING(int moveid, int killid, int x, int y);// 判断象能不能移动bool canMoveXIANG(int moveid, int killid, int x, int y);// 判断马能不能移动bool canMoveMA(int moveid, int killid, int x, int y);// 判断車能不能移动bool canMoveCHE(int moveid, int killid, int x, int y);// 判断炮能不能移动bool canMovePAO(int moveid, int killid, int x, int y);// 判断将能不能移动bool canMoveJIANG(int moveid, int killid, int x, int y);// 输入行列坐标判断该坐标上有没有棋子bool beChess(int row, int col);// 输入行列坐标获取棋子的idint getChessId(int row, int col);// 计算即将行走的棋子与某一坐标之间有几颗棋子int numChess(int moveid, int x, int y);// 判断两个棋子是否是同一方的bool sameColor(int id1, int id2);

接着在 chessarea.cpp 中实现具体的方法描述:

// 输入行列坐标判断该坐标上有没有棋子
bool ChessArea::beChess(int row, int col)
{for(int i=0;i<32;i++)if(myChess[i].row==row && myChess[i].col==col&&!myChess[i].isDead)return true;return false;
}// 计算即将行走的棋子与某一坐标之间有几颗棋子
int ChessArea::numChess(int moveid, int x, int y)
{int i;int sum = 0; //记录中间有几颗棋子if(myChess[moveid].row == x) {if(y-myChess[moveid].col > 0)    //计算下列{for(i=myChess[moveid].col+1; i<y; i++){if(beChess(myChess[moveid].row, i) == true)sum++;    //记录中间有几颗棋子}}else /* 计算上列 */{for(i=myChess[moveid].col-1; i>y; i--){if(beChess(myChess[moveid].row,i)==true)sum++;}}return sum;}else if(myChess[moveid].col == y){if(x - myChess[moveid].row > 0){for(i=myChess[moveid].row+1; i<x; i++){if(beChess(i, myChess[moveid].col)==true)sum++;}}else {for(i=myChess[moveid].row-1; i>x; i--){if(beChess(i, myChess[moveid].col)==true)sum++;}}return sum;}//两个棋子不在一条直线上return -1;
}

numChess 函数的实现要依赖beChess函数,beChess函数实现就是检查一遍输入参数的横纵坐标和棋子的横纵坐标是否相同。numChess函数借用beChess函数,在同一直线上,计算移动前和移动后的横纵坐标差值,再根据差值检测该位置上面是否存在棋子,如果存在棋子那么sum就自加,如果没有,那么两个棋子就不在同一根直线,则返回-1。numChess函数在后面的車和炮行走规则中起关键作用,下面开始实现各个棋子的行走规则。

士的走法:

bool ChessArea::canMoveSHI(int moveid, int killid, int x, int y)
{// 判断士行走是否超了出米字格范围if (myChess[moveid].isRed) {if(y<7 || x<3 || x>5) return false;}else {if(y>2 || x<3 || x>5) return false;}// 判断是否为沿着对角线斜着行走int dx = myChess[moveid].row - x;int dy = myChess[moveid].col - y;if(abs(dx)==1 && abs(dy)==1)return true;return false;
}

要想让士沿着对角线斜着走,那么就要让士移动前后的横坐标差的绝对值和纵坐标差的绝对值都为1,否则士不能移动。

兵的走法:

bool ChessArea::canMoveBING(int moveid, int killid, int x, int y)
{int dx = myChess[moveid].row - x;int dy = myChess[moveid].col - y;if (myChess[moveid].isRed) {// 红方棋子,过河前的行走规则if(myChess[moveid].col>=5 && myChess[moveid].col<=6) {if(dy==1 && dx==0)  //竖着走,不回头return true;else                //横着走,走不通return false;}else /* 过河后 */{if (abs(dy)==1 && abs(dx)==0||(abs(dx)==1 && abs(dy)==0)) {if(dy == -1)         //竖着走return false;    //竖着走走了回头路就要返回错误else                 //横着走return true;}else   return false;}}else /* 黑棋 */{// 黑方棋子,过河前的行走规则if (myChess[moveid].col>= 3 && myChess[moveid].col<=4) {if(dy == -1 && dx==0)   //竖着走,不回头return true;else                    //横着走,走不通return false;}else /* 过河后 */{if(abs(dx)==1&&abs(dy)==0||(abs(dy)==1&&abs(dx)==0)){if(dy == 1)         //竖着回头走,走不通return false;else                //横着走,一样走得通return true;}else    return false;}}return false;
}

兵的走法比士的走法复杂,考虑的细节也较多。首先无论兵有没有过河都不能回头走,过河后,兵才能向左右走。根据这个规则代码可以分为红方和黑方的兵过河前和过河后四个方面进行处理,这样子逻辑比较容易理解。

马的走法:

bool ChessArea::canMoveMA(int moveid, int killid, int x, int y)
{// 获取移动前和移动后的坐标差int dx = myChess[moveid].row - x;int dy = myChess[moveid].col - y;// 获取移动前和移动后的坐标差的中值坐标int medium_x = (myChess[moveid].row + x)/2;int medium_y = (myChess[moveid].col + y)/2;if(abs(dx)==1&&abs(dy)==2 || (abs(dx)==2&&abs(dy)==1)){if(abs(dx)==2){// 别马腿检验if(beChess(medium_x, myChess[moveid].col)==false)return true;}else if(abs(dy)==2){// 别马腿检验if(beChess(myChess[moveid].row, medium_y)==false)return true;}}return false;
}

马的走法是走日字格,那么就有两种情况,一种是横坐标绝对值差为2,纵坐标绝对值差为 1,还有一种是纵坐标绝对值差为2,横坐标绝对值差为 1。除了这样之后,还要注意别马脚判断,那么依靠横纵坐标差的中值坐标可以获取到中值坐标,根据这个坐标值,调用beChess函数判断在该位置是否有棋子别马脚,如果有棋子那么不能走。

象的走法:

bool ChessArea::canMoveXIANG(int moveid, int killid, int x, int y)
{// 象不能过河 if (myChess[moveid].isRed) {if(y<5)return false;}else/* 黑象 */{if(y>4)return false;}//走田字格int dx = myChess[moveid].row - x;int dy = myChess[moveid].col - y;int medium_x = (myChess[moveid].row + x)/2;int medium_y = (myChess[moveid].col + y)/2;if(abs(dx)==2 && abs(dy)==2){//别象眼检验if(!beChess(medium_x, medium_y))return true;}return false;
}

如果懂了前面马的走法,那么象的走法就比较简单了,基本相似。注意象也是需要做别象脚检测。

車的走法:

bool ChessArea::canMoveCHE(int moveid, int killid, int x, int y)
{if(numChess(moveid, x, y) == 0)return true;return false;
}

車的走法有了前面numChess的铺垫,那么就可以变得很简洁。

炮的走法:

bool ChessArea::canMovePAO(int moveid, int killid, int x, int y)
{// 不吃棋子    if(numChess(moveid, x, y)==0 && killid==-1)return true;// 吃棋子if( numChess(moveid,x, y)==1 && killid!=-1)return true;return false;
}

炮的走法和車的很相似,能走沿着直线走,但炮和車唯一的不同就是:炮是隔着一个棋子才能吃棋子。

将的走法:

bool ChessArea::canMoveJIANG(int moveid, int killid, int x, int y)
{//flag_be用来存放位于同一列上的两个将之间棋子的个数int flag_be = -1;int step    = 0;//列超出范围if(x<3 || x>5)return false;//行、列坐标差int dx = myChess[moveid].row - x;int dy = myChess[moveid].col - y;//判断步长是否为1if((abs(dx)==1&&abs(dy)==0) || (abs(dx)==0&&abs(dy)==1))step = 1;if(myChess[moveid].isRed)   // 红棋{// 要杀掉的棋子必须是对面的老将且与对面的老将在同一列上if(killid == 16 && myChess[moveid].row == myChess[16].row){flag_be = numChess(moveid, x, y);if(flag_be == 0)return true;}// 在田字格里面行走if(y<=9 && y>=7 && step==1)return true;}//黑棋else{//要杀掉的棋子必须是对面的老将且与对面的老将在同一列上if(killid == 0 && myChess[moveid].row == myChess[0].row){flag_be =numChess(moveid, x, y);if(flag_be == 0)return true;}//在田字格里面行走if(y>=0 && y<=2 && step==1)return true;}return false;
}

棋子将的走法只能在米字格里面走,每次只能走一个步长,另外注意,当双方的将在同一直线上,而且没有隔着任何棋子时,那么将就可以吃掉对方的将。

Qt开发之中国象棋篇(四):棋子移动(上)相关推荐

  1. 【C++课程设计】期末大作业 - 基于Qt开发的中国象棋软件

    1 题目 基于Qt的中国象棋软件开发 本博客只是简略的描述论文的大致结构.框架,以及软件开发的大致过程.有兴趣的参考原文档资料. 2总体设计与主要功能 2.1概述 中国象棋是起源于中国的一种棋,属于二 ...

  2. Qt终极教程——用Qt编程实现中国象棋游戏(提供源代码和程序编译运行教程)

    Qt终极教程--用Qt编程实现中国象棋游戏 目录 Qt终极教程--用Qt编程实现中国象棋游戏 简介 运行可执行程序体验象棋游戏 Qt 安装 源代码的编译.运行与调试 生成预编译的可执行程序 简介 本文 ...

  3. QT小游戏——中国象棋

    QT小游戏--中国象棋 前言 项目整体结构 棋子类 棋盘类 几个重要方法 1.坐标转化 2.移动规则 3.悔棋和撤销 项目文件 前言 最近用qt做了个中国象棋的小游戏. 目前只能左右互博,支持悔棋.效 ...

  4. 开源力作, 使用 C# 开发的中国象棋

    Chess Chess 是一个基于 C# WPF开发的功能完善的中国象棋软件, 已开源全部源码,开箱即用.代码中含有大量注释,能够快速理解程序流程.可用于二次开发和学习. 功能特性 1. 人机对战,测 ...

  5. 手机软件开发入门 - 中国象棋(1)090308

    最近迷恋起中国象棋来了.我棋力很一般,但是总感觉人生如棋,每一个决定都会影响将来局势的发展.深思熟虑者,后势就比较占优.沉着应战,方显人生力量.刚好,2月份的时候把我的一部使用了快两年的三星普通手机换 ...

  6. Unity3D 2019.3开发的中国象棋的源代码

    Unity3D 2019.3开发的中国象棋的源代码 1 ChessEnum public enum ChessSide {RED,BLACK,Barrier } public enum ChessTy ...

  7. 使用QT简单制作中国象棋之棋盘

    最近在网上看了一些QT的教学视频,就想着将学习的知识运用一下,学到绘图后就想着制作一个简易的中国象棋.目前只做出了棋盘,大概有点样子了. 本例使用的QWidget作为父类创建的加了UI的项目,但目前U ...

  8. java中白盒测试用例_基于JAVA开发的中国象棋游戏的开发与研究白盒测试用例.doc...

    中国象棋白盒测试用例 文件状态当前版本V1.0草稿 作 者梁世聪完成日期2012/6/17文档模板SSP-VER-T13-V1.0密 级变更历史 版本完成日期变更记录作者批准签字V1.02012/6/ ...

  9. java中国象棋棋盘放置棋子,JAVA简易文字版中国象棋

    大二时制作的JAVA简易文字版中国象棋,现在放出,希望大家喜欢! // Java core packages import java.awt.*; import java.awt.event.*; / ...

最新文章

  1. 火狐不支持event.keyCode,用jquery中的event.which轻松解决。
  2. JS调用后台带参数的方法
  3. 关于几种编码的那些事
  4. Koa nuxt最佳实践前篇
  5. python socket编程之双方相互通信简单实例_Python socket实现的简单通信功能示例
  6. Arthas 3.1.2 版本发布 | 增加 logger/heapdump/vmoption 命令
  7. 吃下去的东西老是往上翻上来_食管裂孔疝的这个诱因你知道吗?医生:不要再吃过烫的食物...
  8. idea中的一个子模块中的pom文件带横线、maven为灰色
  9. 基于QT实现简单的音乐播放器
  10. 基于Springboot实现仓库管理系统
  11. java常用工具下载
  12. 5分钟,带你创建一个智能电梯检测器模型
  13. DEL计算机英语翻译,哥德尔计算机,G·del computer,音标,读音,翻译,英文例句,英语词典...
  14. css-图片旋转木马3D效果
  15. 判定通视的计算法公式_水准仪的后视和前视怎么区别?计算公式是什么?
  16. 鸟哥的Linux私房菜:首次登陆与在线求助,LINUX最简单的命令及应用(一)
  17. 反向安装jar包到本地仓库和清除本地仓库中未下载成功的jar包
  18. Linux系统配置网络环境的图文教程(完整版)
  19. FreeRTOS笔记篇:第四章 -- 队列管理
  20. 企业网络如何实现升级

热门文章

  1. 哔哩大学计算机学院:如何学好C语言
  2. java微信公众号多客服_WPF 实现微信公众号多客服(效果实现篇)
  3. 4N60-ASEMI高压N沟道MOS管4N60
  4. 混在IT-(12)夹板下的详细设计报告
  5. IJCAI2023模板pdfinfo报错
  6. 程序员如何写出优雅的代码?
  7. 线性代数学习指导与MATLAB编程实践,线性代数学习指导与MATLAB编程实践
  8. 很老的文章:Mapbar:地图搜索的人民战争
  9. 安全隐私协议合规的那些事
  10. CCNA考试错点总结