Use QT to simply make the placement of Chinese chess pieces

Posted by tmswenson on Sat, 29 Jan 2022 22:35:23 +0100

1 Introduction

   to make chess, chess pieces are essential, but after looking for them online for a long time, it's hard to find satisfactory and supporting chess pieces, and some need VIP download. So I adjust the size through QT's label writing function, then draw a circle outside the label using qpaintevent, and finally run the screenshot to have a piece. But another thing about the pieces in the screenshot is that there is a white part outside the circle, as shown below

   so I prepared to P the picture myself, thinking about finding a free version of PS on the Internet. After a circle of fruitless search, I went to various blog forums to see, and finally found a way to download Baidu online disk. As we all know, Baidu network disk non member download has a 60s high-speed download channel. However, the compressed package that needs to be downloaded is more than 3 G, which still needs to wait a long time to complete the download. During this period, they will drum up their own QT code.

   after several minutes of waiting, the download is finally completed. I'm excited to think about it. I'm here for free PS!! Hahaha, as a result, at the moment I clicked to open the compressed package, I got a password. Then I looked at its installation tutorial and wrote a website. I needed to spend money to buy a password. I threw up. It is impossible to spend money, and then go online to find a tool to crack the password. However, after two, I forgot my name. Anyway, it has no effect and wastes a lot of time. Finally, my roommate recommended me to WeChat's attention to the official account software manager, and finally download it successfully.

   finally, the method of using PS online is not detailed here. Finally, the desired effect is achieved. The effect is as follows.

Have you found that it is no different from the previous picture? Hahaha, let's find a background comparison, so it's easy to find.

2. Text

Note that this project is only a simple implementation, so the upper part is black and the lower part is red.
I said a lot of nonsense. Now let's get to the point.
First, a separate class should be created for the chess piece to store the type of the piece, the picture of the piece, the camp it belongs to, whether it is eaten (the picture of the piece will not be loaded after being eaten), and the current position (the x and y values on the chessboard).

Chess.h header file

#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); // Overload assignment constructor

    // Starting from 0, the types of chess pieces are soldiers, chariots, horses, elephants (phase), scholars (official) and generals (handsome)
    enum TYPE{ARMY,PAO,CAR,HORSE,XIANG,SHI,MASTE};

    // The chess piece belongs to camp red = 0, black = 1
    enum BELONG{RED,BLACK};

signals:
public:
    // Initialize pieces
    void initChess(const int);
public:
    int x;
    int y;// The X and Y coordinates of the chess piece will change when it moves (it can also be represented by rows and columns, but x and y are more intuitive)
    int chessType; // Chess piece type
    int chessBelong; // Chess player's camp
    int chessId; // Chess piece ID
    bool isDead; // Are the pieces eaten
    QString chessPic; // Chess piece picture
};

#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 ;
    // Initialize chess piece id
    chessId = id;

    // Initialize the camp. The top is black and the bottom is red
    if(id < 16)
        chessBelong = BLACK;
    else
        chessBelong = RED;

    // Initial pieces exist
    isDead = false;

    // Initialize chess piece type and position
    // The initialization sequence is black - > red. Black initializes from top to bottom and from left to right
    //                     The Red Square is initialized from bottom to top and from left to right
    // The coordinates of the upper left corner of the chessboard are (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;
    }
    // Initialize picture
    if(id < 16){ // Black Square
        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{ // Red Square
        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;
        }
    }
}

Then you need to define two arrays in the chessboard class. Chess array is used to store 32 pieces, label array is used to load pieces, and label number combination chess array subscripts correspond one by one. That is, a chess corresponds to a label. ChessSize is used to set the size of the chessboard grid, which is used a lot later.

// The size of the piece is the size of the grid
    int ChessSize;
// 32 pieces
    Chess chess[32];
    QLabel* label[32];

Define an init() function to load the label according to the starting position of the chess piece.

void Widget::init(){
    for(int i = 0; i < 32; i++){
        chess[i].initChess(i);
        // Use QLabel to load chess picture
        label[i] = new QLabel(this);
        label[i]->resize(ChessSize,ChessSize);
        label[i]->setPixmap(QPixmap(chess[i].chessPic));
                // Auto fit picture size
        label[i]->setScaledContents(true);
        label[i]->setGeometry(chess[i].x*ChessSize - ChessSize/2,
                           chess[i].y*ChessSize - ChessSize/2,
                           ChessSize,
                           ChessSize
                           );
        label[i]->show();
    }
}

Finally, the chessboard constructor calls init()

// Set the size of the piece, that is, the size of the grid
    this->ChessSize = 50;
    // Fixed window size to chessboard size
    this->setMinimumSize(500,550);
    this->setMaximumSize(500,550);
    
    // Initialize the pieces on the chessboard
    init();

The final effect is as follows

Topics: C++ Game Development