Qt实现简单拼图游戏


前言

自己简单实现了下拼图功能.本来开始只是想显示个图片的。


演示图

请添加图片描述
![请添加图片描述](https://img-blog.csdnimg.cn/c71922e2babf4404bf2805129f13ff76.gif请添加图片描述

提示:以下是本篇文章正文内容,下面案例可供参考

1.ShowWidget.h

代码如下(示例):

#ifndef SHOWWIDGET_H
#define SHOWWIDGET_H

#include <QLabel>
#include <QPainter>
#include <QPixmap>
#include <QVBoxLayout>
#include <QWidget>
#include <QDebug>
#include <QPaintEvent>
#include <QDrag>
#include <QMimeData>

class ShowWidget : public QWidget
{
    Q_OBJECT

public:
    ShowWidget(QWidget *parent = nullptr);
    ~ShowWidget();
    void paintEvent(QPaintEvent *paint);
    QString getStrIndexFriendly() const;
    void setStrIndexFriendly(const QString &value);
    void startDrag();

signals:
    void sendData(int num1, int num2);
private:
    QLabel* m_ImgLab;
    QLabel* m_InvertedImgLab;
    QVBoxLayout* m_MainLayout;
    QString strIndexFriendly;
    bool bMouseEnter = false;				//记录鼠标是否进入窗口
    bool bMousePress = false;
    bool bChecked = false;                   //是否选中
    QPoint startPos;
private:
    void enterEvent(QEvent *event) Q_DECL_OVERRIDE;
    void leaveEvent(QEvent *event) Q_DECL_OVERRIDE;
    void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
    void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
    void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
    void dragEnterEvent(QDragEnterEvent *event);
    void dragMoveEvent(QDragMoveEvent *event);
    void dropEvent(QDropEvent *event);
};

#endif // SHOWWIDGET_H

2.ShowWidget.cpp

代码如下(示例):

#include "showwidget.h"

#include <QApplication>

ShowWidget::ShowWidget( QWidget *parent)
    : QWidget(parent)
{
    this->setAcceptDrops(true);
}
ShowWidget::~ShowWidget()
{

}
void ShowWidget::paintEvent(QPaintEvent *paint)
{
    Q_UNUSED(paint);
    QRect rcBody = rect();
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);  // 反锯齿;
    painter.setPen(Qt::NoPen);
    //画一圈红色的外框
    if (bMouseEnter || bChecked)
    {
        painter.setPen(QPen(QColor(255, 0, 0)));
        painter.drawRoundRect(rcBody,20,20);
    }
    //绘制背景
    QColor colorBackGround = QColor(155, 155, 155);
    if (bMouseEnter || bChecked)
        colorBackGround = QColor(180, 180, 180);
    painter.setBrush(colorBackGround);
    //绘制底图
    if (property("background-image").isValid())
    {
         QImage imageData = property("background-image").value<QImage>();
        if (!imageData.isNull())
            painter.setBrush(imageData.scaled(rcBody.size()));
    }
    painter.drawRoundedRect(rcBody, 5, 5);
    //绘制文字
    QString strIndexFriendly = getStrIndexFriendly();
    int nSize = qMin(width(), height());
    nSize = qMin(nSize, 18);
    if (bMouseEnter || bChecked)
        nSize = qMin(nSize+2, 22);
    QFont font;
    font.setPixelSize(nSize);
    painter.setFont(font);
    painter.setPen(Qt::white);
    if (bMouseEnter || bChecked)
        painter.setPen(Qt::black);
    painter.drawText(rect(), Qt::AlignCenter, strIndexFriendly);
}

QString ShowWidget::getStrIndexFriendly() const
{
    return strIndexFriendly;
}

void ShowWidget::setStrIndexFriendly(const QString &value)
{
    strIndexFriendly = value;
}

void ShowWidget::enterEvent(QEvent *event)
{
    Q_UNUSED(event);
    bMouseEnter = true;
    update();
}

void ShowWidget::leaveEvent(QEvent *event)
{
    Q_UNUSED(event);
    bMouseEnter = false;
    update();
}

void ShowWidget::mouseMoveEvent(QMouseEvent *event)
{
    if (!acceptDrops())
        return;
    if (!bMousePress)
        return;
    if (!(event->buttons() & Qt::LeftButton))
        return;
    int distance = (event->pos()-startPos).manhattanLength();
    if (distance>=QApplication::startDragDistance())
        startDrag();
}

void ShowWidget::mousePressEvent(QMouseEvent *event)
{
    if (event->button()==Qt::LeftButton)
    {
        bMousePress = true;
        startPos = event->pos();
    }

    QWidget::mousePressEvent(event);
}

void ShowWidget::mouseReleaseEvent(QMouseEvent *event)
{
    if(event->button() & Qt::LeftButton)
        bMousePress = false;
}


void ShowWidget::startDrag()
{
    QDrag *drag = new QDrag(this);
    QMimeData *mimeData = new QMimeData;
    mimeData->setText(getStrIndexFriendly());
    drag->setMimeData(mimeData);
    QPixmap pixmap = this->grab();
    if (!pixmap.isNull())
    {
        //设置缩略图
        drag->setPixmap(pixmap);
        //设置鼠标在缩略图上的位置
        drag->setHotSpot(QPoint(0, pixmap.height()/2));
        drag->exec();
    }
}

void ShowWidget::dragEnterEvent(QDragEnterEvent *event)
{
    event->setDropAction(Qt::MoveAction);
    event->accept();
}

void ShowWidget::dragMoveEvent(QDragMoveEvent *event)
{
    event->setDropAction(Qt::MoveAction);
    event->accept();
}

void ShowWidget::dropEvent(QDropEvent *event)
{
    QString str = event->mimeData()->text();
    QString arr = getStrIndexFriendly();
    emit sendData(str.toInt(),arr.toInt());
    event->setDropAction(Qt::MoveAction);
    event->accept();
}

3.MainWindow.h

代码如下(示例):

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QFileDialog>
#include <QGridLayout>
#include <QDragEnterEvent>
#include <QDropEvent>
#include <QMimeData>
#include <QMessageBox>
#include <QDesktopServices>
#include <QRandomGenerator>
#include "showwidget.h"

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

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

private slots:
    void on_pushButton_clicked();
    void on_lineEdit_2_textEdited(const QString &arg1);
    void on_lineEdit_textEdited(const QString &arg1);
    void getData(int num1, int num2);
    void on_pushButton_2_clicked();
    void on_pushButton_3_clicked();

private:
    Ui::MainWindow *ui;
    int xcount = 3, ycount = 4;
    QGridLayout *gridLayoutScreenMap;			//屏幕窗口表格布局
    QList<ShowWidget *> ShowWidgetList;
    QList<QImage > myimage;
    QMap<int, QImage > imagelist;
    QList<int > rnum;
    QList<int > correctnum;
    QString fileName;
    int UsedTime = 0;
    int TotleTime = 0;
private:
    void dragEnterEvent(QDragEnterEvent *event);
    void dropEvent(QDropEvent *event);
};
#endif // MAINWINDOW_H


4.MainWindow.cpp

代码如下(示例):

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    setWindowTitle("拼图游戏---陈淞(可拖动图片)");
    setToolTip("可拖拽图片到窗口添加资源");
    gridLayoutScreenMap = new QGridLayout(this);
    gridLayoutScreenMap->setContentsMargins(0, 0, 0, 0);
    gridLayoutScreenMap->setSpacing(4);
    int number = 0;
    for (int i = 0; i < xcount; i++)
    {
        for (int j = 0; j < ycount; j++)
        {
            number++;
            ShowWidget *pSc = new ShowWidget(this);
            ShowWidgetList.append(pSc);
            connect(pSc,&ShowWidget::sendData,this,&MainWindow::getData);
            pSc->setStrIndexFriendly(QString::number(number));
            pSc->update();
            gridLayoutScreenMap->addWidget(pSc, i, j);
        }
    }
    for (int i = 0; i < xcount*ycount; i++)
    {
        correctnum.append(i);
    }
    TotleTime = xcount*ycount+5;
    ui->label_3->setText(QString("已用次数: %1").arg(0));
    ui->label_5->setText(QString("总共次数: %1").arg(TotleTime));
    ui->lineEdit_2->setText(QString::number(xcount));
    ui->lineEdit->setText(QString::number(ycount));
    ui->pushButton_3->hide();
    this->setAcceptDrops(true);
    ui->widget->setLayout(gridLayoutScreenMap);
}

MainWindow::~MainWindow()
{
    delete ui;
}


void MainWindow::on_pushButton_clicked()
{
    fileName = QFileDialog::getOpenFileName(this,"选择图片","C:/Users/Administrator/Pictures/","图片文件(*.png *.bmp *.jpg)");
    QPixmap pix;
    QPixmap pixmap;
    pix.load(fileName);
    int nycopy = 0,nxcopy = 0,number = 0;
    for (int i = 0; i < xcount; i++)
    {
        for (int j = 0; j < ycount; j++)
        {
            number++;
            pixmap = pix.copy(nxcopy,nycopy,pix.width()/ycount,pix.height()/xcount);
            QImage image;
            image = pixmap.toImage();
            imagelist.insert(number - 1, image);
            pixmap.scaled(ShowWidgetList.at(number - 1)->width(),ShowWidgetList.at(number - 1)->height());
            ShowWidgetList.at(number - 1)->setProperty("background-image", image);
            ShowWidgetList.at(number - 1)->setStrIndexFriendly(QString::number(number));
            ShowWidgetList.at(number - 1)->update();
            gridLayoutScreenMap->addWidget(ShowWidgetList.at(number - 1), i, j);
            nxcopy += pix.width()/ycount;
        }
        nxcopy = 0;
        nycopy += pix.height()/xcount;
    }
    UsedTime = 0;
    TotleTime = xcount*ycount+5;
    ui->label_3->setText(QString("已用次数: %1").arg(UsedTime));
    ui->label_5->setText(QString("总共次数: %1").arg(TotleTime));
    rnum.clear();
    while (rnum.count() < xcount*ycount)
    {
        rnum.append(QRandomGenerator::global()->bounded(xcount*ycount));
        rnum.toSet().toList();
        for (int i = 0; i < rnum.count(); i++)
        {
            for (int j = 0; j < rnum.count(); j++)
            {
                if(rnum.at(i) == rnum.at(j) && (i != j))
                    rnum.removeAt(i);
            }
        }
    }
    for (int i = 0; i < ShowWidgetList.count(); i++)
    {
        ShowWidgetList.at(i)->setProperty("background-image", imagelist.value(rnum.at(i)));
        ShowWidgetList.at(i)->update();
    }
}

//拖动进入事件
void MainWindow::dragEnterEvent(QDragEnterEvent *event)
{
    //检查拖放文件的 MIME 类型信息 拖放的是一个 text/uri-list 数据
    if (event->mimeData()->hasFormat("text/uri-list"))
    {
        //我们在事件处理代码中调用 acceptProposeAction()函数,就可以向用户暗示,你可以将拖动的对象放在这个组件上
        event->acceptProposedAction();
    }
    else
    {
        event->ignore();
    }
}

//放下事件
void MainWindow::dropEvent(QDropEvent *event)
{
    const QMimeData *mimeData = event->mimeData();
    if(mimeData->hasUrls())
    {
        QList<QUrl>urlList = mimeData->urls();
        fileName = urlList.at(0).toLocalFile();
        if(!fileName.isEmpty())
        {
            QPixmap pix;
            QPixmap pixmap;
            pix.load(fileName);
            int nycopy = 0,nxcopy = 0,number = 0;
            for (int i = 0; i < xcount; i++)
            {
                for (int j = 0; j < ycount; j++)
                {
                    number++;
                    pixmap = pix.copy(nxcopy,nycopy,pix.width()/ycount,pix.height()/xcount);
                    QImage image;
                    pixmap.scaled(ShowWidgetList.at(number - 1)->width(),ShowWidgetList.at(number - 1)->height());
                    image = pixmap.toImage();
                    imagelist.insert(number - 1, image);
                    ShowWidgetList.at(number - 1)->setProperty("background-image", image);
                    ShowWidgetList.at(number - 1)->setStrIndexFriendly(QString::number(number));
                    ShowWidgetList.at(number - 1)->update();
                    gridLayoutScreenMap->addWidget(ShowWidgetList.at(number - 1), i, j);
                    nxcopy += pix.width()/ycount;
                }
                nxcopy = 0;
                nycopy += pix.height()/xcount;
            }
        }
    }
    UsedTime = 0;
    TotleTime = xcount*ycount+5;
    ui->label_3->setText(QString("已用次数: %1").arg(UsedTime));
    ui->label_5->setText(QString("总共次数: %1").arg(TotleTime));
    rnum.clear();
    while (rnum.count() < xcount*ycount)
    {
        rnum.append(QRandomGenerator::global()->bounded(xcount*ycount));
        rnum.toSet().toList();
        for (int i = 0; i < rnum.count(); i++)
        {
            for (int j = 0; j < rnum.count(); j++)
            {
                if(rnum.at(i) == rnum.at(j) && (i != j))
                    rnum.removeAt(i);
            }
        }
    }
    for (int i = 0; i < ShowWidgetList.count(); i++)
    {
        ShowWidgetList.at(i)->setProperty("background-image", imagelist.value(rnum.at(i)));
        ShowWidgetList.at(i)->update();
    }
}

void MainWindow::on_lineEdit_2_textEdited(const QString &arg1)
{
    QPixmap pix;
    QPixmap pixmap;
    pix.load(fileName);
    xcount = arg1.toInt();
    int nycopy = 0,nxcopy = 0,number = 0;
    foreach (auto *pSc, ShowWidgetList)
    {
        pSc->disconnect();
        gridLayoutScreenMap->removeWidget(pSc);
        delete pSc;
        pSc = nullptr;
    }
    ShowWidgetList.clear();
    for (int i = 0; i < xcount; i++)
    {
        for (int j = 0; j < ycount; j++)
        {
            number++;
            pixmap = pix.copy(nxcopy,nycopy,pix.width()/ycount,pix.height()/xcount);
            ShowWidget *pSc = new ShowWidget(this);
            connect(pSc,&ShowWidget::sendData,this,&MainWindow::getData);
            pixmap.scaled(pSc->width(),pSc->height());
            QImage image;
            image = pixmap.toImage();
            ShowWidgetList.append(pSc);
            imagelist.insert(number - 1, image);
            pSc->setProperty("background-image", image);
            pSc->setStrIndexFriendly(QString::number(number));
            pSc->update();
            gridLayoutScreenMap->addWidget(pSc, i, j);
            nxcopy += pix.width()/ycount;
        }
        nxcopy = 0;
        nycopy += pix.height()/xcount;
    }
    UsedTime = 0;
    TotleTime = xcount*ycount+5;
    ui->label_3->setText(QString("已用次数: %1").arg(UsedTime));
    ui->label_5->setText(QString("总共次数: %1").arg(TotleTime));
    correctnum.clear();
    for (int i = 0; i < xcount*ycount; i++)
    {
        correctnum.append(i);
    }
    rnum.clear();
    while (rnum.count() < xcount*ycount)
    {
        rnum.append(QRandomGenerator::global()->bounded(xcount*ycount));
        rnum.toSet().toList();
        for (int i = 0; i < rnum.count(); i++)
        {
            for (int j = 0; j < rnum.count(); j++)
            {
                if(rnum.at(i) == rnum.at(j) && (i != j))
                    rnum.removeAt(i);
            }
        }
    }
    for (int i = 0; i < ShowWidgetList.count(); i++)
    {
        ShowWidgetList.at(i)->setProperty("background-image", imagelist.value(rnum.at(i)));
        ShowWidgetList.at(i)->update();
    }
}

void MainWindow::on_lineEdit_textEdited(const QString &arg1)
{
    QPixmap pix;
    QPixmap pixmap;
    pix.load(fileName);
    ycount = arg1.toInt();
    int nycopy = 0,nxcopy = 0,number = 0;
    foreach (auto *pSc, ShowWidgetList)
    {
        pSc->disconnect();
        gridLayoutScreenMap->removeWidget(pSc);
        delete pSc;
        pSc = nullptr;
    }
    ShowWidgetList.clear();
    for (int i = 0; i < xcount; i++)
    {
        for (int j = 0; j < ycount; j++)
        {
            number++;
            pixmap = pix.copy(nxcopy,nycopy,pix.width()/ycount,pix.height()/xcount);
            ShowWidget *pSc = new ShowWidget(this);
            connect(pSc,&ShowWidget::sendData,this,&MainWindow::getData);
            pixmap.scaled(pSc->width(),pSc->height());
            QImage image;
            image = pixmap.toImage();
            ShowWidgetList.append(pSc);
            imagelist.insert(number - 1, image);
            pSc->setProperty("background-image", image);
            pSc->setStrIndexFriendly(QString::number(number));
            pSc->update();
            gridLayoutScreenMap->addWidget(pSc, i, j);
            nxcopy += pix.width()/ycount;
        }
        nxcopy = 0;
        nycopy += pix.height()/xcount;
    }
    UsedTime = 0;
    TotleTime = xcount*ycount+5;
    ui->label_3->setText(QString("已用次数: %1").arg(UsedTime));
    ui->label_5->setText(QString("总共次数: %1").arg(TotleTime));
    correctnum.clear();
    for (int i = 0; i < xcount*ycount; i++)
    {
        correctnum.append(i);
    }
    rnum.clear();
    while (rnum.count() < xcount*ycount)
    {
        rnum.append(QRandomGenerator::global()->bounded(xcount*ycount));
        rnum.toSet().toList();
        for (int i = 0; i < rnum.count(); i++)
        {
            for (int j = 0; j < rnum.count(); j++)
            {
                if(rnum.at(i) == rnum.at(j) && (i != j))
                    rnum.removeAt(i);
            }
        }
    }
    for (int i = 0; i < ShowWidgetList.count(); i++)
    {
        ShowWidgetList.at(i)->setProperty("background-image", imagelist.value(rnum.at(i)));
        ShowWidgetList.at(i)->update();
    }
}

void MainWindow::getData(int num1, int num2)
{
    qDebug()<< "num1 = " << num1 << "num2 = " << num2;
    qDebug()<< "ShowWidgetList.count() = " << ShowWidgetList.count();
    QImage image = ShowWidgetList.at(num1 - 1)->property("background-image").value<QImage>();
    ShowWidgetList.at(num1 - 1)->setProperty("background-image", ShowWidgetList.at(num2 - 1)->property("background-image").value<QImage>());
    ShowWidgetList.at(num2 - 1)->setProperty("background-image",image);
    ShowWidgetList.at(num1 - 1)->update();
    ShowWidgetList.at(num2 - 1)->update();

    UsedTime++;
    ui->label_3->setText(QString("已用次数: %1").arg(UsedTime));
    rnum.swap(num1 - 1, num2 - 1);
    qDebug()<< "rnum = " << rnum << "correctnum = " << correctnum;
    if(correctnum == rnum)
    {
        QMessageBox::information(this,"恭喜","恭喜您成功完成拼图!",QMessageBox::Ok);
        UsedTime = 0;
        TotleTime = xcount*ycount+5;
        ui->label_3->setText(QString("已用次数: %1").arg(UsedTime));
        ui->label_5->setText(QString("总共次数: %1").arg(TotleTime));
    }
    if(TotleTime == UsedTime)
    {
        QMessageBox::warning(this,"抱歉","很遗憾您未能在规定次数内完成拼图!",QMessageBox::Ok);
        UsedTime = 0;
        TotleTime = xcount*ycount+5;
        ui->label_3->setText(QString("已用次数: %1").arg(UsedTime));
        ui->label_5->setText(QString("总共次数: %1").arg(TotleTime));
        ui->pushButton_3->show();
    }
}

void MainWindow::on_pushButton_2_clicked()
{
    QPixmap pix;
    QPixmap pixmap;
    pix.load(fileName);
    int nycopy = 0,nxcopy = 0,number = 0;
    for (int i = 0; i < xcount; i++)
    {
        for (int j = 0; j < ycount; j++)
        {
            number++;
            pixmap = pix.copy(nxcopy,nycopy,pix.width()/ycount,pix.height()/xcount);
            QImage image;
            image = pixmap.toImage();
            imagelist.insert(number - 1, image);
            pixmap.scaled(ShowWidgetList.at(number - 1)->width(),ShowWidgetList.at(number - 1)->height());
            ShowWidgetList.at(number - 1)->setProperty("background-image", image);
            ShowWidgetList.at(number - 1)->setStrIndexFriendly(QString::number(number));
            ShowWidgetList.at(number - 1)->update();
            gridLayoutScreenMap->addWidget(ShowWidgetList.at(number - 1), i, j);
            nxcopy += pix.width()/ycount;
        }
        nxcopy = 0;
        nycopy += pix.height()/xcount;
    }
    UsedTime = 0;
    TotleTime = xcount*ycount+5;
    ui->label_3->setText(QString("已用次数: %1").arg(UsedTime));
    ui->label_5->setText(QString("总共次数: %1").arg(TotleTime));
    rnum.clear();
    while (rnum.count() < xcount*ycount)
    {
        rnum.append(QRandomGenerator::global()->bounded(xcount*ycount));
        rnum.toSet().toList();
        for (int i = 0; i < rnum.count(); i++)
        {
            for (int j = 0; j < rnum.count(); j++)
            {
                if(rnum.at(i) == rnum.at(j) && (i != j))
                    rnum.removeAt(i);
            }
        }
    }
    for (int i = 0; i < ShowWidgetList.count(); i++)
    {
        ShowWidgetList.at(i)->setProperty("background-image", imagelist.value(rnum.at(i)));
        ShowWidgetList.at(i)->update();
    }
}

void MainWindow::on_pushButton_3_clicked()
{
    for (int i = 0; i < ShowWidgetList.count(); i++)
    {
        ShowWidgetList.at(i)->setProperty("background-image", imagelist.value(i));
        ShowWidgetList.at(i)->update();
    }
    ui->pushButton_3->hide();
}


请添加图片描述

源码下载

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值