一、添加棋子类
添加新文件 -> C++ -> C++ Class,类名ChessPieces
棋子头文件chesspieces.h
#ifndef CHESSPIECES_H
#define CHESSPIECES_H
#include <QString>
/*枚举所有棋子的类型 车 马 象 士 将 炮 兵*/
enum TYPE{CHE, MA, XIANG, SHI, JIANG, PAO, BING};
struct Pos{
int row;
int col;
TYPE type;
};
class ChessPieces
{
public:
int ID; /*棋子ID*/
int row; /*棋子在棋盘上所处的行*/
int col; /*棋子在棋盘上所处的列*/
bool isDead; /*棋子是否已死*/
bool isRed; /*棋子是否为红方*/
TYPE type; /*棋子的类型(名字)*/
ChessPieces(); /*构造函数*/
void init(int id); /*初始化棋子*/
QString name(); /*获取棋子的类型(名字)*/
};
#endif // CHESSPIECES_H
棋子实现chesspieces.cpp
#include "chesspieces.h"
ChessPieces::ChessPieces()
{
ID = -1;
row = -1;
col = -1;
type = BING;
isDead = true;
isRed = false;
}
/*棋子初始化*/
void ChessPieces::init(int id)
{
struct Pos pos[16] = {
{0,0,CHE},
{0,1,MA},
{0,2,XIANG},
{0,3,SHI},
{0,4,JIANG},
{0,5,SHI},
{0,6,XIANG},
{0,7,MA},
{0,8,CHE},
{2,1,PAO},
{2,7,PAO},
{3,0,BING},
{3,2,BING},
{3,4,BING},
{3,6,BING},
{3,8,BING},
};
ID = id;
isDead = false;
isRed = id<16;
if(id<16) {
row = pos[id].row;
col = pos[id].col;
type = pos[id].type;
} else {
row = 9-pos[id-16].row;
col = 8-pos[id-16].col;
type = pos[id-16].type;
}
}
/*获取棋子的类型(名字)*/
QString ChessPieces::name()
{
switch (type) {
case CHE:
return "车";
break;
case MA:
return "马";
break;
case XIANG:
return "象";
break;
case SHI:
return "士";
break;
case JIANG:
return "将";
break;
case PAO:
return "炮";
break;
case BING:
return "兵";
break;
default:
return "帅";
break;
}
}
二、棋子的绘制
通过重绘事件绘制棋子
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); /*绘制棋子*/
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; /*棋盘格子边长*/
selectID = -1;
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));
}
/*将棋盘行、列坐标转换成像素坐标*/
QPoint ChessBoard::center(int row, int col)
{
return QPoint(origin.x()+sideLen*col, origin.y()+sideLen*row);
}
效果图