通过鼠标事件实现棋子移动(还没实现每个棋子的移动规则,所以可以随便移动,随便吃棋子,只要轮到走棋的话)

1、判断鼠标左键点击的位置是否为棋盘合法位置

2、只有在棋盘的行、列交叉点为中心的圆圈(刚好是处于圆形棋子范围内)内才合法

3、如果已经选中了棋子,点击的位置也合法则考虑移动棋子

4、如果没有选中棋子,点击的位置也合法则考虑选择棋子

chessboard.h头文件

#ifndef CHESSBOARD_H
#define CHESSBOARD_H#include <QWidget>
#include <QPaintEvent>
#include <QMouseEvent>
#include <QPainter>
#include <QPoint>
#include <QRect>
#include <QPen>#include "chesspieces.h"class ChessBoard : public QWidget
{Q_OBJECT
public:QPoint origin;  /*棋盘原点坐标*/int sideLen;    /*棋盘格子边长*/int selectID;   /*被选中的棋子*/bool redGo;     /*是否轮到红方走*/ChessPieces pieces[32]; /*32颗棋子*/explicit ChessBoard(QWidget *parent = nullptr); /*构造函数*/void paintEvent(QPaintEvent *); /*重绘事件,绘制棋盘、棋子等*/void drawRightAngle(QPainter &pt, QPoint c);    /*绘制棋子炮的停靠点(绘制几个直角)*/void drawPieces(QPainter &pt, int id);  /*绘制棋子*/void mouseReleaseEvent(QMouseEvent *);  /*鼠标事件,选中棋子,移动棋子等*/bool onChessBoard(QPoint c, int &row, int &col); /*判断点击的位置是否合法(是否在棋盘坐标的棋子范围内),同时计算出对应的棋盘行列坐标*/int getPiecesID(int row, int col);  /*获取棋盘行列位置上的棋子*/void toSelectPieces(int id);    /*选择棋子*/void toMovePieces(int targetid, int row, int col);  /*将选中的棋子移动到目标位置*/bool canSelect(int id); /*棋子是否能被选中*/bool isSameColor(int id1, int id2); /*判断两个棋子是否为同一方(颜色相同)*/QPoint center(int row, int col);    /*将棋盘行、列坐标转换成像素坐标*/bool canMove(int moveid, int targetid, int row, int col);   /*判断选中的棋子能否移动到目标位置*/signals:public slots:
};#endif // CHESSBOARD_H

chessboard.cpp实现文件

#include "chessboard.h"ChessBoard::ChessBoard(QWidget *parent) : QWidget(parent)
{setWindowTitle(tr("中国象棋"));origin = QPoint(60,60);  /*棋盘原点坐标*/sideLen = 60;    /*棋盘格子边长*/selectID = -1;redGo = true;resize(origin.x()*3+sideLen*8, origin.y()*2+sideLen*9);/*初始化32颗棋子*/for(int i=0; i<32; i++) {pieces[i].init(i);}
}/*重绘事件*/
void ChessBoard::paintEvent(QPaintEvent *)
{QPainter painter(this);QPen pen;pen.setWidth(3);painter.setPen(pen);/*绘制棋盘外廊框*/painter.drawRect(QRect(origin.x()-5,origin.y()-5, sideLen*8+10, sideLen*9+10));/*绘制棋盘外围*/pen.setWidth(1);painter.setPen(pen);painter.drawRect(QRect(origin, center(9,8)));/*绘制剩下的8横7竖*/for(int i=1; i<=8; i++) {painter.drawLine(center(i,0), center(i,8));if(i<8) {painter.drawLine(center(0,i), center(4,i));painter.drawLine(center(5,i), center(9,i));}}/*绘制九宫斜线*/painter.drawLine(center(0,3), center(2,5));painter.drawLine(center(2,3), center(0,5));painter.drawLine(center(7,3), center(9, 5));painter.drawLine(center(9,3), center(7,5));/*绘制楚河、汉界*/painter.setPen(Qt::gray);painter.setFont(QFont("system", 24, sideLen/2));painter.drawText(QRect(center(4,1), center(5,3)), "楚河", QTextOption(Qt::AlignCenter));painter.drawText(QRect(center(4,5), center(5,7)), "汉界", QTextOption(Qt::AlignCenter));/*绘制直角(棋子炮的停靠点)*/drawRightAngle(painter, center(2,1));drawRightAngle(painter, center(2,7));drawRightAngle(painter, center(7,1));drawRightAngle(painter, center(7,7));/*绘制32颗棋子到棋盘*/for(int i=0; i<32; i++) {drawPieces(painter, i);}
}/*绘制棋子炮的停靠点(绘制几个直角)*/
void ChessBoard::drawRightAngle(QPainter &pt, QPoint c)
{int x = c.x();int y = c.y();int r = sideLen/10;pt.drawLine(x-2*r, y-r, x-r, y-r);pt.drawLine(x-2*r, y+r, x-r, y+r);pt.drawLine(x+r, y-r, x+2*r, y-r);pt.drawLine(x+r, y+r, x+2*r, y+r);pt.drawLine(x-r, y-2*r, x-r, y-r);pt.drawLine(x-r, y+r, x-r, y+2*r);pt.drawLine(x+r, y-2*r, x+r, y-r);pt.drawLine(x+r, y+r, x+r, y+2*r);
}/*绘制棋子到棋盘*/
void ChessBoard::drawPieces(QPainter &pt, int id)
{/*假如棋子已死,就不绘制*/if(pieces[id].isDead) {return;}int r = sideLen/2;   /*棋子半径*//*获取棋子中心点的像素坐标,根据中心点坐标绘制棋子*/QPoint c = center(pieces[id].row, pieces[id].col);/*根据棋子中心点的像素坐标,计算出棋子上面的文字所在的矩形*/QRect rect = QRect(c.x()-r, c.y()-r, sideLen, sideLen);/*红方棋子设置文字为红色*/if(pieces[id].isRed) {pt.setPen(Qt::red);} else {pt.setPen(Qt::black);}/*设置棋子背景颜色为黄色,被鼠标选中的设为绿色*/if(selectID == id) {pt.setBrush(QBrush(Qt::green));} else {pt.setBrush(QBrush(Qt::yellow));}/*绘制棋子为圆形*/pt.drawEllipse(c, r, r);/*绘制棋子文字*/pt.drawText(rect, pieces[id].name(),QTextOption(Qt::AlignCenter));
}/*鼠标事件,选中棋子,移动棋子等*/
void ChessBoard::mouseReleaseEvent(QMouseEvent *ev)
{/*判断是否为鼠标左键*/if(ev->button() != Qt::LeftButton) {return;}/*判断点击的位置是否合法(是否在棋盘坐标的棋子范围内),同时计算出对应的棋盘行列坐标*/int row, col;if(!onChessBoard(ev->pos(), row, col)) {return;}/*获取当前坐标上的棋子*/int id = getPiecesID(row, col);if(selectID == -1) {/*选择棋子*/toSelectPieces(id);} else {/*移动棋子*/toMovePieces(id, row, col);}
}/*将选中的棋子移动到目标位置*/
void ChessBoard::toMovePieces(int targetid, int row, int col)
{/*如果目标棋子和被选中的棋子为同一方则重写选中目标棋子*/if(targetid != -1 && isSameColor(selectID, targetid)) {toSelectPieces(targetid);return;}/*判断选中的棋子能否移动到目标位置*/if(!canMove(selectID, targetid, row, col)) {return;}if(targetid != -1) {pieces[targetid].isDead = true;}pieces[selectID].row = row;pieces[selectID].col = col;/*棋子移动后切换到另一方走棋*/selectID = -1;redGo = !redGo;update();
}/*判断两个棋子是否为同一方(颜色相同)*/
bool ChessBoard::isSameColor(int id1, int id2)
{if(id1 == -1 || id2 == -1) {return false;}return pieces[id1].isRed == pieces[id2].isRed;
}/*选择棋子*/
void ChessBoard::toSelectPieces(int id)
{/*判断棋子是否存在*/if(id == -1) {return;}/*判断棋子是否能够被选中*/if(!canSelect(id)) {return;}selectID = id;update();
}/*棋子是否能被选中*/
bool ChessBoard::canSelect(int id)
{return redGo == pieces[id].isRed;
}/*获取棋盘行列位置上的棋子*/
int ChessBoard::getPiecesID(int row, int col)
{for(int i=0; i<32; i++) {if(!pieces[i].isDead && pieces[i].row==row && pieces[i].col==col) {return i;}}return -1;
}/*判断点击的位置是否合法(是否在棋盘坐标的棋子范围内),同时计算出对应的棋盘行列坐标*/
bool ChessBoard::onChessBoard(QPoint c, int &row, int &col)
{int r = sideLen/2;int x = c.x() - origin.x();int y = c.y() - origin.y();row = y/sideLen;    /*计算当前点击位置在棋盘上所处的行坐标*/col = x/sideLen;    /*计算当前点击位置在棋盘上所处的列坐标*//*四舍五入*/if(y%sideLen > r) {row++;}if(x%sideLen > r) {col++;}int dx = center(row,col).x()-c.x();int dy = center(row,col).y()-c.y();/*计算当前点击的位置到棋盘行列交点(也就是棋子圆心)位置的距离是否小于棋子半径*//*通过直角三角形勾股定理a^2+b^2=c^2计算是否在棋子圆形范围内*/if(dx*dx + dy*dy < r*r) {return true;}return false;
}/*将棋盘行、列坐标转换成像素坐标*/
QPoint ChessBoard::center(int row, int col)
{return QPoint(origin.x()+sideLen*col, origin.y()+sideLen*row);
}/*判断选中的棋子能否移动到目标位置*/
bool ChessBoard::canMove(int moveid, int targetid, int row, int col)
{return true;
}

效果图

Qt中国象棋之棋子的移动相关推荐

  1. Qt中国象棋之棋子的实现

    一.添加棋子类 添加新文件 -> C++ -> C++ Class,类名ChessPieces 棋子头文件chesspieces.h #ifndef CHESSPIECES_H #defi ...

  2. Qt实现中国象棋:(四)棋子绘制的实现

    一.棋子图片的简要介绍 上图就是所要使用到的棋子图片,以"r"开头命名的均为红棋,以"b"开头命名的是黑棋:其中带有红色边框的棋子表示将要被移动的棋子(被选中的 ...

  3. Qt实现中国象棋:(六)棋子移动规则

    一.移动规则的制定 关于中国象棋游戏棋子移动规则有马走日,象走田等说法,下面就将各类棋子的移动规则进行说明及实现(开局时默认红棋在下方,黑棋在上方).棋子移动规则中fromX.fromY为起始点坐标, ...

  4. Qt中国象棋四——显示棋子可移动位置/项目完成

    点击上方蓝字可关注公众号,方便下次阅读~ 先看段视频! 经过上次的介绍,剩下的只是一些逻辑的调整.距离基本版的完成已经比较接近了. 在介绍显示棋子可移动区域前,先介绍下棋子  的可移动位置算法. 1. ...

  5. 使用QT简单制作中国象棋之棋子的摆放

    1 引子   要制作象棋,棋子是必不可少的,但是在网上找了很久,没有找到满意且配套的棋子,有的还需要VIP下载就很难受.于是自己通过QT的标签写字功能调整大小,然后使用绘图事件(QPaintEvent ...

  6. Qt中国象棋一—— Qt 2D 绘图入门

    最近想用Qt写一个中国象棋的项目,在网上找了几个例子后,发现关于绘图部分基础为0 ,于是根据项目需要学习一下.查了一些网上的资料,在此总结一下:我比较喜欢的方式是用到什么学什么,或者自己想做一个东西, ...

  7. 用java定义中国象棋的棋子_中国象棋棋子定义代码java

    棋盘和棋子 象棋是棋子共三十二个,分为红黑两组,各十六个,由对弈双方各执一组,兵种是一样的,分为七种: 红方:帅.仕.相.车.马.炮.兵 黑方:将.士.象.车.马.炮.卒 其中帅与将.仕与士.相与象. ...

  8. java中国象棋棋盘放置棋子,Qt中国象棋二——棋盘与棋子的绘制

    上次和大家分享了Qt的2D绘图基础知识,这样可以更好地理解象棋中一些关于绘图的程序.这次要和大家分享的则是棋盘与棋子的绘制,也可以说是Qt 2D绘图的一些具体应用. 源程序是我在网上找的,而且是下载了 ...

  9. Qt中国象棋二——棋盘与棋子的绘制

    上次和大家分享了Qt的2D绘图基础知识,这样可以更好地理解象棋中一些关于绘图的程序.这次要和大家分享的则是棋盘与棋子的绘制,也可以说是Qt 2D绘图的一些具体应用. 源程序是我在网上找的,而且是下载了 ...

最新文章

  1. Bootstrap学习遇到的role属性--- 无障碍网页应用属性
  2. 吴恩达机器学习006分类问题
  3. Java队列 Queue
  4. Android隐藏媒体文件,如何仅在Android中过滤相关的媒体文件?
  5. Magicodes.IE 2.2里程碑需求和建议征集
  6. c++ 调用labview_Namisoft解析基于Labview的自动化精密阻抗分析系统
  7. 你在用FastReport.Net报表工具做报表没
  8. springboot发送垃圾邮件
  9. FPGA之JESD204B接口——总体概要 实例 中
  10. The Feynman Technique The Best Way to Learn Anything理查德•弗曼学习法
  11. U盘量产-FC1179-453C98B3766B
  12. NLP-Pearson相关系数计算公式及代码
  13. DRM在Android中
  14. OpenCV 保存视频
  15. Linux 查找项目路径
  16. 贝茜的报复(dfs + 位运算)
  17. AcWing 1293. 夏洛克和他的女朋友
  18. ps制作食品网页总结
  19. linux如何管理进程,在嵌入式linux中进程是怎么管理的
  20. You have installed a lot of useless repos and Yum is not working properly becaus

热门文章

  1. HBuilder的安装与试用
  2. dp的sst模式下training流程
  3. 推荐搜索系统中关于多场景学习的常见方法
  4. 前端UI:element-ui,ant-design-vue
  5. char和nchar,varchar和nvarchar 之间的区别
  6. VS2013如何生成exe文件以及如何更改exe程序图标
  7. 【测试基础】Linux系统组成、目录结构及基本命令
  8. linux命令行下写for语句,Linux命令行 – 流程控制:for 循环
  9. [Camera Drv]开video dynamic framerate,特定场景下video encode时会闪屏 - MTK物联网在线解答 - 技术论坛
  10. 消息中间件原理及JMS简介(2)