中国象棋简介
中国象棋是起源于中国的一种棋戏,属于二人对抗性游戏的一种,在中国有着悠久的历史。由于用具简单,趣味性强,成为流行极为广泛的棋艺活动。
棋盘简介
- 直线
棋盘上较长的平行排列的边称为直线,共有9条,其中7条被河界隔断。用红色棋子一方的直线从右往左依次用中文数字一、二、三、四、五、六、七、八、九表示;用黑色棋于一方的直线在红方对面也从右往左依次用阿拉伯数字1、2、3、4、5、6、7、8、9表示。
- 横线
棋盘上较短的平行排列的边称为横线。横线共有10条,用红色棋子一方的横线从红方底线算起,从下往上依次用中文数字一至十表示;用黑色棋子一方的横线则从黑方底线开始,依次用阿拉伯数字1-10表示。
- 交叉点
直线与横线相交的地方称为“交叉点”。整个棋盘共有90个交叉点,棋子就摆放和活动在这些交叉点上。
- 河界
棋盘中央没有画直线的地方称为“河界”。它代表弃战双方的分界线,确定了各自的地域。
- 九宫
棋盘两端各画有斜交叉线的地方称为“九宫”。将则只能在各自“九宫”的9个交叉点上活动。
棋子
所有的棋子共有三十二个,其中又分为红、黑两组(分别代表对垒的一方),每组共有十六个棋子(为了区别双方的棋子,不仅在颜色中有所区别,而且还会使用同音不同字的棋子),其中又各分为七种棋子,其名称和数目如下:
红棋子:帅一个,车、马、炮、相、士各两个,兵五个。
黑棋子:将一个,车、马、炮、象、士各两个,卒五个。
通过Qt5实现中国象棋
Qt5纯代码实现中国象棋,通过paintEvent绘制事件绘制棋盘和棋子
通过重绘事件绘制棋盘和棋子,通过鼠标事件实现棋子移动等
设计思路
- 绘制棋盘
- 绘制棋子
- 走棋
- 走棋规则
一、新建项目
新建项目 -> 其他项目 -> Empty qmake Project,项目名填myChinessChess
添加新文件 -> C++ -> C++ Source File,文件名main.cpp
工程文件myChinessChess.pro添加一行
QT += widgets gui
二、添加棋盘类
添加新文件 -> C++ -> C++ Class,类名ChessBoard,Base class选QWidget
main.cpp文件内容如下,可以先运行一下
#include <QApplication>
#include "chessboard.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
ChessBoard board;
board.show();
return app.exec();
}
棋盘头文件chessboard.h头文件中
#ifndef CHESSBOARD_H
#define CHESSBOARD_H
#include <QWidget>
#include <QPaintEvent>
#include <QPainter>
#include <QPoint>
#include <QRect>
#include <QPen>
class ChessBoard : public QWidget
{
Q_OBJECT
public:
QPoint origin; /*棋盘原点坐标*/
int sideLen; /*棋盘格子边长*/
explicit ChessBoard(QWidget *parent = nullptr); /*构造函数*/
void paintEvent(QPaintEvent *); /*重绘事件*/
void drawRightAngle(QPainter &pt, QPoint c); /*绘制棋子炮的停靠点(绘制几个直角)*/
QPoint center(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; /*棋盘格子边长*/
resize(origin.x()*3+sideLen*8, origin.y()*2+sideLen*9);
}
/*重绘事件*/
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));
}
/*绘制棋子炮的停靠点(绘制几个直角)*/
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);
}
/*将棋盘行、列坐标转换成像素坐标*/
QPoint ChessBoard::center(int row, int col)
{
return QPoint(origin.x()+sideLen*col, origin.y()+sideLen*row);
}
效果图