美文网首页
qt开发拼图游戏

qt开发拼图游戏

作者: 一路向后 | 来源:发表于2023-07-08 18:43 被阅读0次

1.main.cpp

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

int main(int argc, char **argv)
{
        QApplication app(argc, argv);

        QTextCodec::setCodecForLocale(QTextCodec::codecForName("utf-8"));

        QWidget *pWidget = new MainWindow();

        pWidget->setFixedSize(500, 630);
        pWidget->show();

        return app.exec();
}

2.blocklabel.h

#ifndef _PUZZLE_MAP_BLOCK_H_
#define _PUZZLE_MAP_BLOCK_H_

#include <QLabel>
#include <QPushButton>
#include <QVBoxLayout>

class BlockLabel : public QLabel
{
        Q_OBJECT

public:
        explicit BlockLabel(QWidget *parent = 0);
        ~BlockLabel();

        void setButtonSize(int w, int h);
        void setPosition(int seq);

signals:
        void swap_postion(int seq);

public slots:
        void on_click_slot();

private:
        QVBoxLayout *layout;
        QPushButton *button;
        int seq;
};

#endif

3.blocklabel.cpp

#include "blocklabel.h"
#include <QDebug>

BlockLabel::BlockLabel(QWidget *parent) : QLabel(parent)
{
        QString style = "QPushButton{\nbackground-color:transparent;border:none;color:white;}";
        button = new QPushButton(this);
        layout = new QVBoxLayout(this);

        button->setStyleSheet(style);
        button->setGeometry(0, 0, 0, 0);
        button->setCursor(Qt::PointingHandCursor);
        //button->setSizePolicy(QSizePolicy::Expanding);

        layout->setSpacing(0);
        layout->setContentsMargins(0,0,0,0);
        layout->addWidget(button);
        this->setLayout(layout);

        connect(button, &QPushButton::clicked, this, &BlockLabel::on_click_slot);
}

void BlockLabel::setButtonSize(int w, int h)
{
        button->setFixedWidth(w);
        button->setFixedHeight(h);
}

void BlockLabel::setPosition(int seq)
{
        this->seq = seq;
}

void BlockLabel::on_click_slot()
{
        //qDebug() << "on click: " << seq;

        emit swap_postion(seq);
}

BlockLabel::~BlockLabel()
{
        layout->removeWidget(button);

        delete layout;
        delete button;
}

4.mainwindow.h

#ifndef __MAIN_WINDOW_H_
#define __MAIN_WINDOW_H_

#include <QApplication>
#include <QDesktopWidget>
#include <QMainWindow>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QPixmap>
#include <QWidget>
#include <QVector>
#include <QKeyEvent>
#include <QLabel>
#include <QPushButton>
#include <QSlider>
#include "blocklabel.h"

class MainWindow : public QMainWindow
{
        Q_OBJECT

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

signals:
        void game_win();

public slots:
        void on_block_click(int clickid);
        void on_game_win();
        void on_slider_change(int v);

private:
        void init_board();
        void shift();
        void swap(int i, int j);
        bool check_solved();
        void slide_tile(int emptyid, int clickid);
        int distance(int a, int b);

        int calc_inverse(const std::vector<int> &array, int s);
        bool is_solvable(const std::vector<int> &array, int s);

        int block_empty;
        int blks_width;
        int rows;
        QVBoxLayout *vbox;
        QLabel *thumbnail;
        QLabel *slider_label[2];
        QHBoxLayout *hbox[2];
        QSlider *slider;
        QVector<BlockLabel *> blocks;
        QVector<int> block_seqs;

        bool solved;
};

#endif

5.mainwindow.cpp

#include <algorithm>
#include <vector>
#include <cmath>
#include <QMessageBox>
#include <QDebug>
#include "mainwindow.h"

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
{
    setWindowTitle("拼图游戏");

    blks_width = 480;
    rows = 3;
    int block_width = blks_width / rows;

    solved = false;

    vbox = new QVBoxLayout(this);
    hbox[0] = new QHBoxLayout(this);
    hbox[1] = new QHBoxLayout(this);
    slider = new QSlider(Qt::Horizontal, this);
    slider_label[0] = new QLabel("简单", this);
    slider_label[1] = new QLabel("困难", this);
    thumbnail = new QLabel(this);
    QPixmap pixmap(":/resources/defa.jpg");
    QPixmap thu_pixmap;

    connect(this, &MainWindow::game_win, this, &MainWindow::on_game_win);
    connect(slider, &QSlider::valueChanged, this, &MainWindow::on_slider_change);

    slider_label[0]->setGeometry(70, 57, 60, 30);
    slider_label[1]->setGeometry(240, 57, 60, 30);

    thumbnail->setGeometry(330, 10, 120, 120);
    thu_pixmap = pixmap.scaled(thumbnail->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
    thumbnail->setPixmap(thu_pixmap);

    slider->setGeometry(100, 63, 200, 30);
    slider->setFixedWidth(130);
    slider->setMinimum(0);
    slider->setMaximum(2);
    slider->setValue(0);

    hbox[0]->addWidget(slider_label[0]);
    hbox[0]->addWidget(slider);
    hbox[0]->addWidget(slider_label[1]);
    hbox[0]->addWidget(thumbnail);

    init_board();

    vbox->addLayout(hbox[0]);
    vbox->addLayout(hbox[1]);
    setLayout(vbox);

    //emit game_win();
}

void MainWindow::swap(int i, int j)
{
    int block_width = blks_width / rows;
    int x1 = i % rows;
    int y1 = i / rows;
    int x2 = j % rows;
    int y2 = j / rows;
    int t = 0;

    blocks[block_seqs[i]]->setGeometry(10+x2*block_width, 140+y2*block_width, block_width, block_width);
    blocks[block_seqs[j]]->setGeometry(10+x1*block_width, 140+y1*block_width, block_width, block_width);

    blocks[block_seqs[i]]->setPosition(x2+y2*rows);
    blocks[block_seqs[j]]->setPosition(x1+y1*rows);

    t =  block_seqs[j];
    block_seqs[j] = block_seqs[i];
    block_seqs[i] = t;
}

void MainWindow::shift()
{
    std::vector<int> std_block_seqs(block_seqs.begin(), block_seqs.end());
    std::random_device rd;
    std::mt19937 g(rd());
    int block_width = blks_width / rows;
    int size = std_block_seqs.size();

    while(!is_solvable(std_block_seqs, std_block_seqs[0]))
    {
        std::shuffle(std_block_seqs.begin(), std_block_seqs.end(), g);
    }

    //std_block_seqs = {1, 0, 2, 3, 4, 5, 6, 7, 8};

    for(int i=0; i<size; i++)
    {
        block_seqs[i] = std_block_seqs[i];
    }

    qDebug() << block_seqs;

    for(int i=0; i<block_seqs.size(); i++)
    {
        int x = i % rows;
        int y = i / rows;

        blocks[block_seqs[i]]->setGeometry(10+x*block_width, 140+y*block_width, block_width, block_width);
        blocks[block_seqs[i]]->setPosition(x+y*rows);

        blocks[block_seqs[i]]->show();

        if(i == 0)
        {
            blocks[block_seqs[i]]->hide();

            block_empty = 0;
        }
    }
}

void MainWindow::init_board()
{
    QPixmap pixmap(":/resources/defa.jpg");
    int block_width = blks_width / rows;

    //vbox->setLayout(nullptr);

    for(int i=0; i<blocks.size(); i++)
    {
        hbox[1]->removeWidget(blocks[i]);

        delete blocks[i];

        blocks[i] = NULL;
    }

    blocks.clear();
    block_seqs.clear();

    for(int i=0; i<rows; i++)
    {
        for(int j=0; j<rows; j++)
        {
            BlockLabel *block = new BlockLabel((QWidget*)this);
            QPixmap blk_pixmap = pixmap.copy(j*block_width, i*block_width, block_width, block_width);

            block->setGeometry(10+j*block_width, 140+i*block_width, block_width, block_width);
            block->setButtonSize(block_width, block_width);

            block->setPixmap(blk_pixmap);

            connect(block, &BlockLabel::swap_postion, this, &MainWindow::on_block_click);

            hbox[1]->addWidget(block);

            blocks.push_back(block);
            block_seqs.push_back(j+i*rows);
        }
    }

    shift();

    //vbox->addLayout(hbox[1]);

    solved = false;
}

bool MainWindow::check_solved()
{
    for(int i=0; i<block_seqs.size(); i++)
    {
        if(block_seqs[i] != i)
        {
            return false;
        }
    }

    return true;
}

void MainWindow::slide_tile(int emptyid, int clickid)
{
    if(!solved)
    {
        if(distance(emptyid, clickid) == 1)
        {
            swap(emptyid, clickid);

            this->block_empty = clickid;

            solved = check_solved();

            if(solved)
            {
                emit game_win();
            }
        }
    }
}

int MainWindow::distance(int a, int b)
{
    int x1 = a % rows;
    int y1 = a / rows;
    int x2 = b % rows;
    int y2 = b / rows;

    //qDebug() << "empty (" << x1 << ", " << y1 << ")";
    //qDebug() << "click (" << x2 << ", " << y2 << ")";

    return abs(x1-x2) + abs(y1-y2);
}

void MainWindow::on_block_click(int clickid)
{
    slide_tile(block_empty, clickid);
}

void MainWindow::on_game_win()
{
    QMessageBox::StandardButton msgbox = QMessageBox::information(nullptr, "提示", "你成功了!");

    init_board();
}

void MainWindow::on_slider_change(int v)
{
    rows = v + 3;

    init_board();
}

int MainWindow::calc_inverse(const std::vector<int> &array, int s)
{
    int inverse = 0;
    int size = array.size();

    for(int i=0; i<size; i++)
    {
        for(int j=i+1; j<size; j++)
        {
            if(array[i] > array[j] && array[j] != s)
            {
                inverse++;
            }
        }
    }

    return inverse;
}

bool MainWindow::is_solvable(const std::vector<int> &array, int s)
{
    int inverse = calc_inverse(array, s);
    int empty_row = 0;
    int size = array.size();

    for(int i=0; i<size; i++)
    {
        if(array[i] == s)
        {
            empty_row = i / rows;
            break;
        }
    }

    if(inverse % 2 == 0 && empty_row % 2 == 0 || inverse % 2 != 0 && empty_row % 2 != 0)
    {
        for(int i=0; i<size; i++)
        {
            if(array[i] != i)
            {
                return true;
            }
        }

        return false;
    }

    return false;
}

MainWindow::~MainWindow()
{

}

6.puzzle.pro

QT += core gui network widgets multimedia

TEMPATE = app
TARGET = puzzle
DEPENDPATH += .
INCLUDEPATH += .

RESOURCES += resource.qrc

HEADERS += mainwindow.h blocklabel.h
SOURCES += main.cpp mainwindow.cpp blocklabel.cpp

7.resource.qrc

<RCC>
    <qresource prefix="/">
        <file>resources/defa.jpg</file>
    </qresource>
</RCC>

8.resources/defa.jpg

defa.jpg

相关文章

网友评论

      本文标题:qt开发拼图游戏

      本文链接:https://www.haomeiwen.com/subject/pljjudtx.html