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

1 引子

  要制作象棋,棋子是必不可少的,但是在网上找了很久,没有找到满意且配套的棋子,有的还需要VIP下载就很难受。于是自己通过QT的标签写字功能调整大小,然后使用绘图事件(QPaintEvent)在标签的外部绘制一个圆圈,最后运行截图就有了棋子。但截图的棋子还有一点就是圆圈之外还有白色部分,如下所示
在这里插入图片描述
  于是准备自己将图片P一下,就想着在网上找一个免费版本的PS,找了一圈无果后,就去逛各个博客论坛看看,终于找到一个百度网盘下载的方法。众所周知,百度网盘非会员下载有一个60s的极速下载通道,奈何需要下载的压缩包3个多G,还是要等很久才能下载完成,期间就捣鼓自己的QT代码。

  经过数分钟的等待,终于下载完毕,想想就激动,免费的PS我来啦!!哈哈哈,结果在点开压缩包的一瞬间我蒙了,居然还有密码,然后一看它的安装教程,写了一个网址需要花钱去买密码,我吐了。花钱是不可能花钱的,然后去网上找破解密码的工具,然而用了两个忘了叫啥名字了,反正没有效果,又浪费一堆时间。最后,室友推荐我去微信关注公众号软件管家,终于下载成功了,我**, 你 **不早说。

  最后就是去网上使用PS的方法了,这里就不细说了,最后就达到了自己预想的效果,效果如下。
在这里插入图片描述
有没有发现和前面图片没什么两样哈哈哈,下面找个背景对比一下,这样就容易发现了。
在这里插入图片描述

2. 正文

注意,本项目只是简单实现,因此固定上方为黑方,下方为红方。
前面说了一大堆废话,现在进入正题吧。
首先,应该对棋子单独创建一个类,用于存储该棋子类型,棋子图片,所属阵营,是否被吃(被吃后就不加载该棋子的图片),以及当前位置(棋盘上的x,y值)。

Chess.h头文件

#ifndef CHESS_H
#define CHESS_H

#include <QWidget>

class Chess : public QWidget
{
    Q_OBJECT
public:
    explicit Chess(QWidget *parent = nullptr);
    void operator=(const Chess& c); // 重载赋值构造函数

    // 棋子类型 从0开始为 兵,車,馬,象(相),士(仕),将(帅)
    enum TYPE{ARMY,PAO,CAR,HORSE,XIANG,SHI,MASTE};

    // 棋子所属阵营 red = 0, black = 1
    enum BELONG{RED,BLACK};

signals:
public:
    // 初始化棋子
    void initChess(const int);
public:
    int x;
    int y;// 棋子所在x,y坐标,移动会改变 (也可以使用行列表示,但x,y更直观)
    int chessType; // 棋子类型
    int chessBelong; // 棋子所属阵营
    int chessId; // 棋子ID
    bool isDead; // 棋子是否被吃
    QString chessPic; // 棋子图片
};

#endif // CHESS_H

Chess.cpp

#include "chess.h"

Chess::Chess(QWidget *parent) : QWidget(parent)
{

}

void Chess::operator=(const Chess &c){
    x = c.x;
    y = c.y;
    chessType = c.chessType;
    chessBelong = c.chessBelong;
    chessId = c.chessId;
    isDead = c.isDead;
    chessPic = c.chessPic;
}

void Chess::initChess(const int id){
    if(id > 31 || id < 0)
        return ;
    // 初始化棋子id
    chessId = id;

    // 初始化阵营, 上方为黑,下方为紅
    if(id < 16)
        chessBelong = BLACK;
    else
        chessBelong = RED;

    // 初始都棋子都存在
    isDead = false;

    // 初始化棋子类型和位置
    // 初始化顺序为黑方->紅方,黑方从上往下,从左往右初始化
    //                     红方从下往上,从左往右初始化
    // 棋盘左上角坐标为 (1,1)
    switch(id){
        case 0: y = 1, x = 1, chessType = CAR; break;
        case 1: y = 1, x = 2, chessType = HORSE; break;
        case 2: y = 1, x = 3, chessType = XIANG; break;
        case 3: y = 1, x = 4, chessType = SHI; break;
        case 4: y = 1, x = 5, chessType = MASTE; break;
        case 5: y = 1, x = 6, chessType = SHI; break;
        case 6: y = 1, x = 7, chessType = XIANG; break;
        case 7: y = 1, x = 8, chessType = HORSE; break;
        case 8: y = 1, x = 9, chessType = CAR; break;
        case 9: y = 3, x = 2, chessType = PAO; break;
        case 10: y = 3, x = 8, chessType = PAO; break;
        case 11: y = 4, x = 1, chessType = ARMY; break;
        case 12: y = 4, x = 3, chessType = ARMY; break;
        case 13: y = 4, x = 5, chessType = ARMY; break;
        case 14: y = 4, x = 7, chessType = ARMY; break;
         case 15: y = 4, x = 9, chessType = ARMY; break;

        case 16: y = 10, x = 1, chessType = CAR; break;
        case 17: y = 10, x = 2, chessType = HORSE; break;
        case 18: y = 10, x = 3, chessType = XIANG; break;
        case 19: y = 10, x = 4, chessType = SHI; break;
        case 20: y = 10, x = 5, chessType = MASTE; break;
        case 21: y = 10, x = 6, chessType = SHI; break;
        case 22: y = 10, x = 7, chessType = XIANG; break;
        case 23: y = 10, x = 8, chessType = HORSE; break;
        case 24: y = 10, x = 9, chessType = CAR; break;
        case 25: y = 8, x = 2, chessType = PAO; break;
        case 26: y = 8, x = 8, chessType = PAO; break;
        case 27: y = 7, x = 1, chessType = ARMY; break;
        case 28: y = 7, x = 3, chessType = ARMY; break;
        case 29: y = 7, x = 5, chessType = ARMY; break;
        case 30: y = 7, x = 7, chessType = ARMY; break;
        case 31: y = 7, x = 9, chessType = ARMY; break;
    }
    // 初始化图片
    if(id < 16){ // 黑方
        switch (chessType) {
            case ARMY: chessPic = ":/ChessImage/black_army.png"; break;
            case PAO: chessPic = ":/ChessImage/black_pao.png"; break;
            case CAR: chessPic = ":/ChessImage/black_car.png"; break;
            case HORSE: chessPic = ":/ChessImage/black_horse.png"; break;
            case XIANG: chessPic = ":/ChessImage/black_xiang.png"; break;
            case SHI: chessPic = ":/ChessImage/black_shi.png"; break;
            case MASTE: chessPic = ":/ChessImage/black_maste.png"; break;
        }
    }
    else{ // 红方
        switch (chessType) {
            case ARMY: chessPic = ":/ChessImage/red_army.png"; break;
            case PAO: chessPic = ":/ChessImage/red_pao.png"; break;
            case CAR: chessPic = ":/ChessImage/red_car.png"; break;
            case HORSE: chessPic = ":/ChessImage/red_horse.png"; break;
            case XIANG: chessPic = ":/ChessImage/red_xiang.png"; break;
            case SHI: chessPic = ":/ChessImage/red_shi.png"; break;
            case MASTE: chessPic = ":/ChessImage/red_maste.png"; break;
        }
    }
}

然后需要在棋盘类定义两个数组,chess数组用于存储32个棋子,label数组用于加载棋子,并且label数组合chess数组下标一一对应。也就是一个chess对应一个label。ChessSize用于设置棋盘格子的大小,它在后面使用非常多。

// 棋子大小 即 格子大小
    int ChessSize;
// 32个棋子
    Chess chess[32];
    QLabel* label[32];

定义一个init()函数用于根据棋子的起始位置加载label。

void Widget::init(){
    for(int i = 0; i < 32; i++){
        chess[i].initChess(i);
        // 利用QLabel加载棋子图片
        label[i] = new QLabel(this);
        label[i]->resize(ChessSize,ChessSize);
        label[i]->setPixmap(QPixmap(chess[i].chessPic));
                // 自动适应图片大小
        label[i]->setScaledContents(true);
        label[i]->setGeometry(chess[i].x*ChessSize - ChessSize/2,
                           chess[i].y*ChessSize - ChessSize/2,
                           ChessSize,
                           ChessSize
                           );
        label[i]->show();
    }
}

最后就是棋盘的构造函数调用init()

// 设置 棋子大小, 即格子大小
    this->ChessSize = 50;
    // 固定窗口大小为棋盘大小
    this->setMinimumSize(500,550);
    this->setMaximumSize(500,550);
    
    // 初始化棋子在棋盘上
    init();

最后效果如下
在这里插入图片描述

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值