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
网友评论