Qt——项目:翻转金币游戏

目录

一.示例演示

二.制作思路

(一).准备资源及总体框架

(二).开始窗口

(三).选择关卡窗口

(四).游戏窗口

(五).优化

三.实现代码

(一).自制按钮类

(二).开始窗口

(三).选择关卡窗口

(四).金币类

(五).初始化金币数据类

(六).游戏窗口


一.示例演示

 

二.制作思路

(一).准备资源及总体框架

创建项目后,将资源加载通过创建Qt设计师界面类加载进项目。

(资源已上传个人仓库,有需要请自取:Qt/12.23翻转金币/res · 纽盖特/git all - 码云 - 开源中国 (gitee.com)

大致上,我们需要一个开始游戏的窗口选择关卡的窗口玩游戏的窗口,共三个窗口。 

(二).开始窗口

这个窗口需要使用菜单栏,因此可以用QMainWindow类

此外要设置背景图片,可以使用绘图事件paintEvent完成。

窗口标题及图片直接在构造函数完成,使用setWindowTitle及setWindowIcon完成。

按钮要设置成点击后会向下弹并返回,可以专门定义一个按钮类,使用QPropertyAnimation特效类编写下降和上升的函数。

关卡窗口完成后,使用connect通过信号和槽完成点击按钮就关闭本窗口打开关卡窗口的操作。

(三).选择关卡窗口

 与开始窗口一样,完成背景、标题、菜单栏的搭建。

难点在于关卡按钮和BACK按钮。

关卡按钮使用自制按钮类即可,但需要设置底层图片

该按钮通过QLabel标签类完成关卡号的书写。但这还不够,如果此时connect后点击按钮不会有任何反应,因为此时标签在按钮之上,鼠标相当于直接点在标签上。

需要使用鼠标穿透:lab->setAttribute(Qt::WA_TransparentForMouseEvents); 

使用connect将关卡按钮与第三次游戏窗口连接。

BACK按钮同样使用自制按钮类,但此时不同的是点击后按钮要换图片

对此,我们可以在自制按钮类中定义鼠标事件,点击事件mousePressEvent()内部将图片切换成第二个,释放事件mouseReleaseEvent()内部将图片切换成第一个。

之后将BACK按钮与开始窗口connect连接即可。

(四).游戏窗口

本层的背景、菜单栏、标题搭建与之前一样。

重点是翻转金币和成功动画的跳出。

首先要进一步优化本层BACK按钮,在第二层BACK按钮基础上在窗口构造函数中connect连接BACK按钮与lambda函数,lambda函数内部通过消息对话框QMessageBox完成是否退出的询问。

翻转金币的过程要先定义一个金币类,继承自QPushButton按钮类。内部要实现两个翻转函数,分别是翻成金币和银币,具体翻转过程通过金币类内部定义两个QTimer定时器,当需要翻转时发送start函数,使用connect让lambda函数接收,函数内部根据QTimer定时翻转一小部分,直到全部翻完,stop相关QTimer。

判定成功通过在金币类中定义bool类型成员,翻成金币为true,银币为false。遍历一遍全部是true时说明游戏成功。 

初始化游戏硬币颜色可以再定义一个数据类(dataofcoin.h中),这里面定义一个QMap类,first是记录的层数,second是二维数组,使用0和1分别代表银币和金币。当游戏窗口初始化时,通过调用数据类,根据窗口是哪一关(游戏窗口类有一个成员,当关卡层点击关卡后,该成员会记录这是第几关),调用对应二维数组,完成硬币颜色初始化。

游戏成功后,需要锁定硬币,不能再通过点击硬币翻转同时跳出成功动画。

锁定硬币通过在自制按钮类中定义一个bool成员,当检查游戏成功时设置成true。同时按钮类的鼠标事件判断该成员如果为true就直接退出事件,即点击无效。

跳出成功动画是当检测到成功后,先加载图片到游戏窗口之外(需要注意在构造函数外控件需要调用show函数才能显示,即便是构造函数内的lambda函数内也一样),再通过特效类QPropertyAnimation完成图片的下降。

(五).优化

优化主要有两个:完成音效和完成窗口移动。

音效通过使用QSound类,加载音效路径后调用play函数完成。

窗口移动优化的意思是:假如此时在第二层,如果移动窗口,那么当返回 第一层后窗口就自动回到之前的位置而不是在我们移动后的位置。

 优化方式就是在每一层切回的connect槽函数中先同步切回前上一层窗口的位置,本层窗口打开时直接就是该位置了。具体是通过setGeometry()窗口成员函数完成。

三.实现代码

(一).自制按钮类

//mybutton.h
#ifndef MYBUTTON_H
#define MYBUTTON_H

#include <QMainWindow>
#include<QPushButton>
#include<QEvent>

class myButton : public QPushButton
{
    Q_OBJECT
public:
    explicit myButton(QString firstPath, QString secondPath = "");

    void putDown();
    void putUp();

    void mousePressEvent(QMouseEvent* ev);
    void mouseReleaseEvent(QMouseEvent* ev);

signals:
    void returnToStart();
    void returnToSelect();
private:
    QString normalPath;
    QString pressPath;
};

#endif // MYBUTTON_H
//mybutton.cpp
#include "mybutton.h"
#include<QPixmap>
#include<QIcon>
#include<QPropertyAnimation>
#include<QSound>

myButton::myButton(QString firstPath, QString secondPath)
{
    normalPath = firstPath;
    pressPath = secondPath;
    QPixmap pix;//按钮图片
    pix.load(firstPath);
    this->setFixedSize(pix.width(), pix.height());//设置按钮大小
    this->setStyleSheet("QPushButton{border:Opx}");//解除图片规则限制
    this->setIcon(pix);
    this->setIconSize(QSize(pix.width(), pix.height()));//设置按钮图片大小

}

void myButton::mousePressEvent(QMouseEvent* ev){
    if(pressPath != ""){
        QSound* sound = new QSound(":/res/TapButtonSound.wav", this);
        sound->play();
        QPixmap pix;
        pix.load(":/res/BackButtonSelected.png");
        this->setIcon(pix);
    }
    return QPushButton::mousePressEvent(ev);
}
void myButton::mouseReleaseEvent(QMouseEvent* ev){
    if(pressPath != ""){
        QPixmap pix;
        pix.load(":/res/BackButton.png");
        this->setIcon(pix);
        //emit returnToSelect();//发出返回信号
    }
    return QPushButton::mouseReleaseEvent(ev);
}

void myButton::putDown(){
    //设置特效
    QPropertyAnimation* pro = new QPropertyAnimation(this, "geometry");
    pro->setDuration(500);//设置特效时间
    //设置特效开始与结束
    pro->setStartValue(QRect(x(), y(), width(), height()));
    pro->setEndValue(QRect(x(), y() + 10, width(), height()));
    //设置特效弹跳效果
    pro->setEasingCurve(QEasingCurve::OutBounce);
    pro->start();
}
void myButton::putUp(){
    //设置特效
    QPropertyAnimation* pro = new QPropertyAnimation(this, "geometry");
    pro->setDuration(500);//设置特效时间
    //设置特效开始与结束
    pro->setStartValue(QRect(x(), y() + 10, width(), height()));
    pro->setEndValue(QRect(x(), y(), width(), height()));
    //设置特效弹跳效果
    pro->setEasingCurve(QEasingCurve::OutBounce);
    pro->start();
}

(二).开始窗口

//startwindow.h
#ifndef STARTWINDOW_H
#define STARTWINDOW_H
#include"mybutton.h"
#include"selectwindow.h"

#include <QMainWindow>
#include<QEvent>
QT_BEGIN_NAMESPACE
namespace Ui { class startWindow; }
QT_END_NAMESPACE

class startWindow : public QMainWindow
{
    Q_OBJECT

public:
    startWindow(QWidget *parent = nullptr);
    ~startWindow();

    void paintEvent(QPaintEvent*);
private:
    Ui::startWindow *ui;
};
#endif // STARTWINDOW_H
//selectwindow.cpp
#include "selectwindow.h"

#include<QIcon>
#include<QPixmap>
#include<QPainter>
#include<QMenuBar>
#include<QDebug>
#include<QLabel>
#include<QTimer>

selectWindow::selectWindow(QMainWindow *parent) : QMainWindow(parent)
{
    setFixedSize(360, 620);
    setWindowIcon(QIcon(":/res/Coin0001.png"));
    setWindowTitle("Coin Filp");

    //创建菜单
    QMenuBar* bar = new QMenuBar(this);
    setMenuBar(bar);
    QMenu* start = bar->addMenu("开始");
    QAction* quit = start->addAction("结束");
    connect(quit, &QAction::triggered, [=]{
        close();
    });

    //创建关卡选择
    for(int i = 0; i < 9; i++){
        //每一关按钮
        myButton* but = new myButton(":/res/LevelIcon.png");
        but->setParent(this);
        but->move(50 + i % 3 * 100, 180 + i / 3 * 100);
        //按钮上的标号
        QLabel* lab = new QLabel(this);
        lab->setText(QString().number(i + 1));
        lab->setFixedSize(but->width(), but->height());
        lab->move(50 + i % 3 * 100, 180 + i / 3 * 100);
        lab->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);//设置水平垂直居中
        QFont font;//字体设置
        font.setBold(true);
        font.setFamily("YouYuan");
        font.setPointSize(10);
        lab->setFont(font);
        //按钮穿透
        lab->setAttribute(Qt::WA_TransparentForMouseEvents);

        //建立关卡按钮连接
        connect(but, &QPushButton::clicked, [=]{
            QTimer::singleShot(500, this, [=]{
                gameWindow* game = new gameWindow(i + 1);
                game->setGeometry(geometry());
                game->show();
                this->hide();

                //游戏界面如果按下返回按钮
                connect(game, &gameWindow::returnToSelect, [=]{
                    this->setGeometry(game->geometry());//防止窗口位置与上一层不同
                    this->show();
                    delete game;
                });
            });
        });


    }

    //返回按钮
    myButton* ret = new myButton(":/res/BackButton.png", ":/res/BackButtonSelected.png");
    ret->setParent(this);
    ret->move(width() - ret->width(), height() - ret->height());

    connect(ret, &QPushButton::clicked, [=]{
        emit returnToStart();
    });

}

void selectWindow::paintEvent(QPaintEvent*){
    QPixmap pix;
    bool judge = pix.load(":/res/OtherSceneBg.png");
    if(judge == false) qDebug() << "Load Error";
    QPainter p(this);
    p.drawPixmap(0, 0, width(), height(), pix);
    pix.load(":/res/Title.png");
    p.drawPixmap(width() * 0.5 - pix.width() * 0.5, 30, pix);

}

(三).选择关卡窗口

//selectwindow.h
#ifndef SELECTWINDOW_H
#define SELECTWINDOW_H
#include"mybutton.h"
#include"gamewindow.h"

#include <QMainWindow>

class selectWindow : public QMainWindow
{
    Q_OBJECT
public:
    explicit selectWindow(QMainWindow *parent = nullptr);
    void  paintEvent(QPaintEvent*);

signals:
    void returnToStart();

};
#endif // SELECTWINDOW_H
//selectwindow.cpp
#include "selectwindow.h"

#include<QIcon>
#include<QPixmap>
#include<QPainter>
#include<QMenuBar>
#include<QDebug>
#include<QLabel>
#include<QTimer>

selectWindow::selectWindow(QMainWindow *parent) : QMainWindow(parent)
{
    setFixedSize(360, 620);
    setWindowIcon(QIcon(":/res/Coin0001.png"));
    setWindowTitle("Coin Filp");

    //创建菜单
    QMenuBar* bar = new QMenuBar(this);
    setMenuBar(bar);
    QMenu* start = bar->addMenu("开始");
    QAction* quit = start->addAction("结束");
    connect(quit, &QAction::triggered, [=]{
        close();
    });

    //创建关卡选择
    for(int i = 0; i < 9; i++){
        //每一关按钮
        myButton* but = new myButton(":/res/LevelIcon.png");
        but->setParent(this);
        but->move(50 + i % 3 * 100, 180 + i / 3 * 100);
        //按钮上的标号
        QLabel* lab = new QLabel(this);
        lab->setText(QString().number(i + 1));
        lab->setFixedSize(but->width(), but->height());
        lab->move(50 + i % 3 * 100, 180 + i / 3 * 100);
        lab->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);//设置水平垂直居中
        QFont font;//字体设置
        font.setBold(true);
        font.setFamily("YouYuan");
        font.setPointSize(10);
        lab->setFont(font);
        //按钮穿透
        lab->setAttribute(Qt::WA_TransparentForMouseEvents);

        //建立关卡按钮连接
        connect(but, &QPushButton::clicked, [=]{
            QTimer::singleShot(500, this, [=]{
                gameWindow* game = new gameWindow(i + 1);
                game->setGeometry(geometry());
                game->show();
                this->hide();

                //游戏界面如果按下返回按钮
                connect(game, &gameWindow::returnToSelect, [=]{
                    this->setGeometry(game->geometry());//防止窗口位置与上一层不同
                    this->show();
                    delete game;
                });
            });
        });


    }

    //返回按钮
    myButton* ret = new myButton(":/res/BackButton.png", ":/res/BackButtonSelected.png");
    ret->setParent(this);
    ret->move(width() - ret->width(), height() - ret->height());

    connect(ret, &QPushButton::clicked, [=]{
        emit returnToStart();
    });

}

void selectWindow::paintEvent(QPaintEvent*){
    QPixmap pix;
    bool judge = pix.load(":/res/OtherSceneBg.png");
    if(judge == false) qDebug() << "Load Error";
    QPainter p(this);
    p.drawPixmap(0, 0, width(), height(), pix);
    pix.load(":/res/Title.png");
    p.drawPixmap(width() * 0.5 - pix.width() * 0.5, 30, pix);

}

(四).金币类

//coin.h
#ifndef CION_H
#define CION_H
#include <QWidget>
#include<QPushButton>
#include<QTimer>
#include<QPixmap>

class Coin : public QPushButton
{
    Q_OBJECT
public:
    Coin(int i, int j);
    void Filp();

    QTimer* time1;
    QTimer* time2;
    int subX;
    int subY;
    int min = 1;
    int max = 8;
    bool goldFace;
    bool filpNow = false;
    bool isWin = false;
signals:

};
#endif // CION_H
//coin.cpp
#include "coin.h"

#include<QTimer>
#include<QDebug>

Coin::Coin(int i, int j)
    :subX(i)
    ,subY(j)
    ,time1(new QTimer(this))
    ,time2(new QTimer(this))
{
    connect(time1, &QTimer::timeout, [=]{
        QPixmap pix;
        pix.load(QString(":/res/Coin000%1.png").arg(min++));
        setIconSize(QSize(pix.width(), pix.height()));
        setIcon(pix);
        if(min > max){
            min = 1;
            filpNow = false;
            time1->stop();
        }
    });
    connect(time2, &QTimer::timeout, [=]{
        QPixmap pix;
        pix.load(QString(":/res/Coin000%1.png").arg(max--));
        setIconSize(QSize(pix.width(), pix.height()));
        setIcon(pix);
        if(max < min){
            max = 8;
            filpNow = false;
            time2->stop();
        }
    });
}

void Coin::Filp(){
    if(filpNow == false && isWin == false){
        filpNow = true;
        if(goldFace){//翻成银币
            goldFace = false;
            time1->start(30);
        }
        else{//翻成金币
            goldFace = true;
            time2->start(30);
        }

    }
    else
    {
        return;
    }
}

(五).初始化金币数据类

//dataofcoin.h
#ifndef DATAOFCOIN_H
#define DATAOFCOIN_H
#include <QObject>
#include<QMap>
#include<QVector>

class Data : public QObject
{
    Q_OBJECT
public:
    explicit Data(QObject *parent = nullptr);

    QMap<int, QVector<QVector<int>>> dataMap;//记载每一关初始金币
signals:

};
#endif // DATAOFCOIN_H
//dataofcoin.cpp
#include "dataofcoin.h"

Data::Data(QObject *parent) : QObject(parent)
{
    //第一关
    QVector<QVector<int>> array = {{1, 1, 1, 1},
                                   {1, 1, 0, 1},
                                   {1, 0, 0, 0},
                                   {1, 1, 0, 1}};
    dataMap.insert(1, array);
    //第二关
    array = {{1, 0, 1, 1},
             {0, 0, 1, 1},
             {1, 1, 0, 0},
             {1, 1, 0, 1}};
    dataMap.insert(2, array);
    //第三关
    array = {{0, 0, 0, 0},
             {0, 1, 1, 0},
             {0, 1, 1, 0},
             {0, 0, 0, 0}};
    dataMap.insert(3, array);
    //第四关
    array = {{0, 1, 1, 0},
             {1, 1, 1, 1},
             {0, 0, 0, 0},
             {0, 0, 0, 0}};
    dataMap.insert(4, array);
    //第五关
    array = {{1, 0, 0, 1},
             {1, 0, 0, 1},
             {1, 0, 0, 1},
             {1, 0, 0, 1}};
    dataMap.insert(5, array);
    //第六关
    array = {{0, 0, 1, 0},
             {1, 1, 0, 0},
             {0, 0, 1, 1},
             {0, 1, 0, 0}};
    dataMap.insert(6, array);
    //第七关
    array = {{0, 1, 1, 0},
             {1, 0, 0, 1},
             {1, 0, 0, 1},
             {0, 1, 1, 0}};
    dataMap.insert(7, array);
    //第八关
    array = {{0, 0, 1, 0},
             {0, 0, 0, 1},
             {0, 1, 0, 0},
             {0, 0, 0, 0}};
    dataMap.insert(8, array);
    //第九关
    array = {{0, 0, 0, 0},
             {0, 0, 0, 0},
             {0, 0, 0, 0},
             {0, 0, 0, 0}};
    dataMap.insert(9, array);
}

(六).游戏窗口

//gamewindow.h
#ifndef GAMEWINDOW_H
#define GAMEWINDOW_H
#include"mybutton.h"
#include"coin.h"
#include"dataofcoin.h"

#include <QMainWindow>
#include<QPaintEvent>
#include<QVector>
#include<QPropertyAnimation>

class gameWindow : public QMainWindow
{
    Q_OBJECT
public:
    explicit gameWindow(int level);
    void paintEvent(QPaintEvent*);

signals:
    void returnToSelect();
private:
    void judgeWin();
    int gameLevel;
    bool isWinForButton = false;
    QVector<QVector<Coin*>> arrCoin;


};


#endif // GAMEWINDOW_H
//gamewindow.cpp
#include "gamewindow.h"
#include<QMenuBar>
#include<QPainter>
#include<QIcon>
#include<QPixmap>
#include<QDebug>
#include<QLabel>
#include<QFont>
#include<QMessageBox>
#include<QSound>

gameWindow::gameWindow(int level)
    :QMainWindow()
    ,gameLevel(level)
{
        setFixedSize(360, 620);
        setWindowIcon(QIcon(":/res/Coin0001.png"));
        setWindowTitle("Coin Filp");

        //创建菜单
        QMenuBar* bar = new QMenuBar(this);
        setMenuBar(bar);
        QMenu* start = bar->addMenu("开始");
        QAction* quit = start->addAction("结束");
        connect(quit, &QAction::triggered, [=]{
            close();
        });

        //返回按钮
        myButton* ret = new myButton(":/res/BackButton.png", ":/res/BackButtonSelected.png");
        ret->setParent(this);
        ret->move(width() - ret->width(), height() - ret->height());

        connect(ret, &QPushButton::clicked, [=]{
            //如果完成游戏或者消息对话框选择yes就emit信号函数给关卡层完成游戏层关闭
            if(isWinForButton ||
                    QMessageBox::Yes == QMessageBox::question(this, "warning",\
                              "确定回到选择界面么?",QMessageBox::Yes | QMessageBox::No)){
                    emit returnToSelect();//发送信号函数
        }

        });

        //关卡等级标签
        QLabel* lab = new QLabel(this);
        QFont font;
        font.setFamily("YouYuan");
        font.setPointSize(20);
        font.setBold(true);
        lab->setFont(font);
        lab->setText(QString("Level: %1").arg(gameLevel));
        lab->setFixedSize(ret->width() * 3, ret->height() * 2);
        lab->move(20, height() - lab->height());

        //创建金币矩阵
        Data data;
        for(int i = 0; i < 4; i++){
            arrCoin.push_back(QVector<Coin*>(4));
        }

        for(int i = 0; i < 4; i++){
            for(int j = 0; j < 4; j++){
                //创建背景
                QPixmap pix;
                pix.load(":/res/BoardNode.png");
                QLabel* lab = new QLabel(this);
                lab->setGeometry(0, 0, pix.width(), pix.height());
                lab->setPixmap(pix);
                lab->move(67 + j % 4 * pix.width() * 1.2, 200 + i % 4 * pix.height() * 1.2);

                //创建硬币
                QPixmap pixCoin;
                Coin* coin = new Coin(i, j);
                coin->setParent(this);
                arrCoin[i][j] = coin;
                if(data.dataMap[gameLevel][i][j] == 1){//建金币
                    pixCoin.load(":/res/Coin0001.png");
                    coin->goldFace = true;
                }
                else{//建银币
                    pixCoin.load(":/res/Coin0008.png");
                    coin->goldFace = false;
                }
                //设置币的位置
                coin->setFixedSize(pixCoin.width(), pixCoin.height());
                coin->setStyleSheet("QPushButton{border:Opx}");
                coin->setIcon(pixCoin);
                coin->setIconSize(QSize(pixCoin.width(), pixCoin.height()));
                coin->move(70 + j % 4 * pix.width() * 1.2, 203 + i % 4 * pix.height() * 1.2);

                connect(coin, &QPushButton::clicked, [=]{//硬币翻转
                    QSound* sound = new QSound(":/res/ConFlipSound.wav", this);
                    sound->play();
                    coin->Filp();
                    QTimer::singleShot(200, this, [=]{//延时翻转其他硬币
                        //翻转其他硬币
                        if(i < 3){//下
                            arrCoin[i + 1][j]->Filp();
                        }
                        if(i > 0){
                            arrCoin[i - 1][j]->Filp();
                        }
                        if(j < 3){//右
                            arrCoin[i][j + 1]->Filp();
                        }
                        if(j > 0){
                            arrCoin[i][j - 1]->Filp();
                        }

                        //判断是否胜利
                        judgeWin();
                    });
                });

            }
        }


}

void gameWindow::judgeWin(){
    for(auto& vec : arrCoin){
        for(auto& coin : vec){
            if(coin->goldFace == false) return;
        }
    }
    //此时已经胜利
    QTimer::singleShot(200, this, [=]{
        //播放成功音乐
        QSound* sound = new QSound(":/res/LevelWinSound.wav", this);
        sound->play();
    });
    for(auto& vec : arrCoin){
        for(auto& coin : vec){
            coin->isWin = true;
        }
    }
    isWinForButton = true;
    QPixmap pixWin;//加载成功图片
    pixWin.load(":/res/LevelCompletedDialogBg.png");
    QLabel* labWin = new QLabel(this);
    labWin->setFixedSize(pixWin.width(), pixWin.height());
    labWin->setPixmap(pixWin);
    labWin->setGeometry(0, 0, pixWin.width(), pixWin.height());
    labWin->move(width() * 0.5 - pixWin.width() * 0.5, -pixWin.height());
    labWin->show();//使用show才能展示
    //完成特效
    QPropertyAnimation* pro = new QPropertyAnimation(labWin, "geometry");
    pro->setDuration(1000);
    pro->setStartValue(QRect(labWin->x(), labWin->y(),\
                             labWin->width(), labWin->height()));
    pro->setEndValue(QRect(labWin->x(), 90,\
                             labWin->width(), labWin->height()));
    pro->setEasingCurve(QEasingCurve::OutBounce);
    pro->start();
}

void gameWindow::paintEvent(QPaintEvent*){//绘图事件,创建背景
    QPixmap pix;
    pix.load(":/res/OtherSceneBg.png");
    QPainter p(this);
    p.drawPixmap(0, 0, width(), height(), pix);
    //添加标题图片
    pix.load(":/res/Title.png");
    pix = pix.scaled(pix.width() * 0.5, pix.height() * 0.5);//图片缩放
    p.drawPixmap(0, 30, pix);
}

 

作为一个真正的程序员,首先应该尊重编程,热爱你所写下的程序,他是你的伙伴,而不是工具——未名 


如有错误,敬请斧正

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

就要 宅在家

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值