Qt中国象棋之棋子的实现

一、添加棋子类

添加新文件 -> 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);
}

效果图

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值