QT环境下实现UI界面的拼图

本文介绍了一个基于Qt的九宫格拼图游戏的实现方法。通过随机打乱图片块,用户需通过滑动将其恢复原状。文章详细解释了如何切割、移动图片以及处理鼠标点击事件。

MainWindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QWidget>
#include <QtGui>
#include <QMainWindow>
#include<QLabel>
namespace Ui {
    class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    void cutimage();

    void Random();

    void moveImage();

    void mousePressEvent(QMouseEvent *event);

    void reset();

    QTimer *timer;
    QString strFileName;//文件名
    QImage* pSourceImage;//原图

    QLabel* pLbImage[9];//九宫格label

    QImage pImage[9];
    int pCompare[3][3];//i行j列的初始化图片,将移动后的图片进行比较
    int num=0;
    int tim=0;

private slots:
    void on_new_2_clicked();

    void on_replay_clicked();

    void on_quit_clicked();
    void on_timeOut();

private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H


main.cpp


#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}



mainwindow.cpp


#include "mainwindow.h"
#include "ui_mainwindow.h"
#include<QFileDialog>
#include<QMouseEvent>
#include<QMessageBox>
#include<QTime>
#include<QtGlobal>
#include<QTimer>
#define SMALL_W 100
#define SMALL_H 100
#define PHOTO_X 20
#define PHOTO_Y 40

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    timer=new QTimer(this);             //计时
    connect(timer,SIGNAL(timeout()),SLOT(on_timeOut()));    //连接时间槽

    num=0;
    ui->label_2->setText(QString::number(num));
    tim=0;
    ui->time_label->setText(QString::number(tim));

    pSourceImage=NULL;          //将pSourceImage初始化
    for(int i=0;i<9;i++)        //将label分割成九宫格
    {
        pLbImage[i]= new QLabel(this);
        pLbImage[i]->setGeometry(0,0,SMALL_W,SMALL_H);
        pLbImage[i]->move(PHOTO_X+SMALL_W*(i%3),
                          PHOTO_Y+SMALL_H*(i/3));
        pLbImage[i]->setFrameShape(QFrame::Box);
    }
    this->setStyleSheet(
                "MainWindow{border-image: url(:/beijing.jpg);}");
}

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

void MainWindow::on_new_2_clicked()
{

    //打开对话框
    QString name =
            QFileDialog::getOpenFileName(this,
                                         "select pictures",
                                         "/home/newcapec",
                                         "Images(*.png *.jpg)");
    if(name.isEmpty())
        return ;
    strFileName=name;
   if(NULL!=pSourceImage)       //判断是否为空,如果不是第一次,释放pSourceImage
   {
       delete pSourceImage;
       pSourceImage=NULL;
   }

   pSourceImage = new QImage(strFileName);
   if(NULL==pSourceImage)           //判断是否申请成功
   {
       return ;
   }
   QImage tep=pSourceImage->scaled(ui->label->width(),
                                   ui->label->height());

   ui->label->setPixmap(QPixmap::fromImage(tep));

   cutimage();
}
void MainWindow::cutimage()
{
    QImage temp = pSourceImage->scaled(SMALL_W*3,SMALL_H*3);//缩放
    for(int i=0;i<9;i++)
    {  
        pImage[i]=temp.copy((i%3)*SMALL_W,               //要复制图片的坐标,x,y
                            (i/3)*SMALL_H,
                                     SMALL_W,
                                     SMALL_H);           //图片的大小
        pLbImage[i]->setPixmap(QPixmap::fromImage(pImage[i]));//加载图片

        pCompare[i/3][i%3]=i;                       //初始化
    }

    QPixmap tep(":/blank.jpg");                 //挖空,添加空白图片
    pLbImage[8]->setPixmap(tep);

    Random();
    if(timer->isActive())
    {
        timer->stop();
    }
    timer->start(1000);
}
void MainWindow::Random()//将数组中的数字打乱,即对应的label打乱,然后再一次性打乱图片
{
    num=0;
    ui->label_2->setText(QString::number(num));
    tim=0;
    ui->time_label->setText(QString::number(tim));
    qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
    for(int i=0;i<20;i++)
    {
        int row=0;
        int colum=0;
        for(int j=0;j<9;j++)        //找到空白格的位置
        {
            if(pCompare[j/3][j%3]==8)
            {
                row=j/3;
                colum=j%3;
                break;
            }
        }
        int direction=qrand()%4;  //随机出来一个方向
        switch (direction) {
        case 0:     //up
            if(row<2)       //判断是否越界,计算的是空格的行列数
            {
              pCompare[row][colum]=pCompare[row+1][colum];
              pCompare[row+1][colum]=8;
            }
            break;
        case 1:         //down
             if(row>0)
             {
                 pCompare[row][colum]=pCompare[row-1][colum];
                 pCompare[row-1][colum]=8;
             }
            break;
        case 2:         //left
            if(colum>0)
            {
                pCompare[row][colum]=pCompare[row][colum-1];
                pCompare[row][colum-1]=8;
            }
            break;
        case 3:         //right
            if(colum<2)
            {
                pCompare[row][colum]=pCompare[row][colum+1];
                pCompare[row][colum+1]=8;
            }
            break;
        default:
            break;
        }
    }
    moveImage();
}
void MainWindow::moveImage()        //move label
{
    for(int i=0;i<9;i++)
    {
        int index=pCompare[i/3][i%3];
        pLbImage[index]->move(PHOTO_X+SMALL_W*(i%3),
                              PHOTO_Y+SMALL_H*(i/3));
    }
}
void MainWindow::mousePressEvent(QMouseEvent *event)
{
//    if(NULL==pSourceImage)
//            return ;
    if(!timer->isActive())
        return ;
    bool bflag;
    if(event->button() == Qt::LeftButton)//左键点击
    {

        QPoint pressPoint=event->pos();
        if(pressPoint.x()>PHOTO_X && pressPoint.x()<PHOTO_X+SMALL_W*3 //判断点击的地方是否为图片区域
           &&pressPoint.y()>PHOTO_Y && pressPoint.y()<PHOTO_Y+SMALL_H*3)
        {
            bflag=false;
            int row = (pressPoint.y()-PHOTO_Y)/SMALL_H;
            int col = (pressPoint.x()-PHOTO_X)/SMALL_W;
            if(row>0 && pCompare[row-1][col]==8)            //将图片和空白格移动,四个方向
            {
                pCompare[row-1][col]=pCompare[row][col];
                pCompare[row][col]=8;
                bflag=true;
            }
            else if(row<2 && pCompare[row+1][col]==8)
            {
                pCompare[row+1][col]=pCompare[row][col];
                pCompare[row][col]=8;
                bflag=true;
            }
            else if(col>0 && pCompare[row][col-1]==8)
            {
                pCompare[row][col-1]=pCompare[row][col];
                pCompare[row][col]=8;
                bflag=true;
            }
            else if(col<2 && pCompare[row][col+1]==8)
            {
                pCompare[row][col+1]=pCompare[row][col];
                pCompare[row][col]=8;
                bflag=true;
            }
        }
    }

    if(bflag==true)     //判断复原之后将挖空的那块补全
    {
        moveImage();
        num++;          //记录步数
        ui->label_2->setText(QString::number(num));     //将步数十进制数转化成字符串
        bool bfinish=true;
        for(int i=0;i<9;i++)
        {
            if(pCompare[i/3][i%3]!=i)//如果数组中的值等于初始值,则表示拼好了
                bfinish=false;
            if(bfinish==false)
                break;
        }
        if(bfinish==true)
        {
            timer->stop();
            //qDebug("hhhh");
            pLbImage[8]->setPixmap(QPixmap::fromImage(pImage[8]));      //补全图片

            QMessageBox::about(this, "Sucessful","You are win!");   //游戏成功弹出的对话

        }
    }
}

void MainWindow::on_timeOut()
{
    tim++;
    ui->time_label->setText(QString::number(tim));
}

void MainWindow::on_replay_clicked()      //重来
{
    if(NULL==pSourceImage) return ;
    num=0;
    ui->label_2->setText(QString::number(num));
    tim=0;
    ui->time_label->setText(QString::number(tim));
    Random();
    QPixmap tep(":/blank.jpg");
    pLbImage[8]->setPixmap(tep);
    if(timer->isActive())
    {
        timer->stop();
    }
    timer->start(1000);
}

void MainWindow::on_quit_clicked()      //退出
{
    if (!(QMessageBox::information(this,tr("CT Control View"),tr("Do you really want to quit the game?"),tr("Yes"),tr("No"))))
    {
       this->close();
    }
}




评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值