项目介绍
项目展示:
界面1:
界面2:
项目步骤:
1、创建开始界面窗口
2、跳转到游戏界面窗口
2.1、跳转至游戏界面后,游戏界面初始化,即随机绘画图片(PS:需要按坐标依次绘画出坐标,其次连连看的绘画图片一定是成对出现,否则不能够实现游戏的成功)
2.2、跳转至游戏界面后,开辟线程,该线程中执行进度条的执行和lcd画面的执行
2.3、初始化成功后:捕捉鼠标事件,当点击的图片类型一致时,且满足消除规则后,将图片消除(此处采用的是一个数组来进行的,修改数值的值)
2.4、图片消除后,重新绘制画面,即可实现;且发出信号,设置得分树
3、当分数为100时或剩余时间为0时,游戏结束。
项目代码:
开始界面窗口头文件
#ifndef START_H
#define START_H
#include <QWidget>
#include <QPaintEvent>
#include <QPainter>
#include <QPen>
#include <QMouseEvent>
#include <QRandomGenerator>
#include <QDebug>
#include "mythread.h"
//设置每一个图标的长宽
const int IMAGE_WIDHT=50;
const int IMAGE_HEIGHT=50;
//行数和列数
const int ROW_COUNT=10;
const int COLUMN_COUNT=10;
namespace Ui {
class start;
}
class start : public QWidget
{
Q_OBJECT
public:
explicit start(QWidget *parent = nullptr);
~start();
void paintEvent(QPaintEvent *event); //绘画
void mousePressEvent(QMouseEvent *event); //鼠标点击
void mouseReleaseEvent(QMouseEvent *event);//鼠标释放
bool canBeLinked(int, int, int, int); //判断能否连接函数
bool inTwoLine(int , int , int , int );
bool inOneLine(int , int , int , int );
bool inThreeLine(int, int , int , int );
void newGame(); // 新游戏
void initdate();// 图片的初始化
//signals:
// void Win();
private slots:
void on_pushButton_clicked();
void setbol();
private:
Ui::start *ui;
bool showGameArea = false;
QVector<QVector<bool>>* isEmpty;
int clickCount; //鼠标点击次数
int firstClickX; //点击时的x坐标
int firstClickY; //点击时的Y坐标
int PixmapData[ROW_COUNT][COLUMN_COUNT]; //二维数组,用于记录图片的类型
int lab_data = 0; //lad的信号数字显示
bool win =false;
};
#endif // START_H
开始界面窗口代码:
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
op = new start;
setFixedSize(802,639);
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_pushButton_start_clicked()
{
//开始游戏
this->hide();
op->show();
}
void Widget::on_pushButton_quit_clicked()
{
this->close();
}
游戏界面窗口代码:
#ifndef START_H
#define START_H
#include <QWidget>
#include <QPaintEvent>
#include <QPainter>
#include <QPen>
#include <QMouseEvent>
#include <QRandomGenerator>
#include <QDebug>
#include "mythread.h"
//设置每一个图标的长宽
const int IMAGE_WIDHT=50;
const int IMAGE_HEIGHT=50;
//行数和列数
const int ROW_COUNT=10;
const int COLUMN_COUNT=10;
namespace Ui {
class start;
}
class start : public QWidget
{
Q_OBJECT
public:
explicit start(QWidget *parent = nullptr);
~start();
void paintEvent(QPaintEvent *event); //绘画
void mousePressEvent(QMouseEvent *event); //鼠标点击
void mouseReleaseEvent(QMouseEvent *event);//鼠标释放
bool canBeLinked(int, int, int, int); //判断能否连接函数
bool inTwoLine(int , int , int , int );
bool inOneLine(int , int , int , int );
bool inThreeLine(int, int , int , int );
void newGame(); // 新游戏
void initdate();// 图片的初始化
//signals:
// void Win();
private slots:
void on_pushButton_clicked();
void setbol();
private:
Ui::start *ui;
bool showGameArea = false;
QVector<QVector<bool>>* isEmpty;
int clickCount; //鼠标点击次数
int firstClickX; //点击时的x坐标
int firstClickY; //点击时的Y坐标
int PixmapData[ROW_COUNT][COLUMN_COUNT]; //二维数组,用于记录图片的类型
int lab_data = 0; //lad的信号数字显示
bool win =false;
};
//CPP代码
#endif // START_H
#include "start.h"
#include "ui_start.h"
start::start(QWidget *parent) :
QWidget(parent),
ui(new Ui::start)
{
ui->setupUi(this);
setFixedSize(509,763);
//生成图片
initdate();
//初始化进度条
ui->progressBar->setValue(100);
//开辟一个线程
mythread *t1 = new mythread(1000000000);
connect(t1, SIGNAL(valueChanged(int)), ui->progressBar, SLOT(setValue(int)));
connect(t1, SIGNAL(opvalue(int)), ui->lcdNumber,SLOT(display(int)));
connect(t1, SIGNAL(gameover()), this,SLOT(setbol()));
t1->start();
}
start::~start()
{
delete ui;
}
void print_lab(int ){
}
void start:: paintEvent(QPaintEvent *event){
QPainter p(this);
for(int i=0;i<ROW_COUNT;++i)
for(int j=0;j<COLUMN_COUNT;++j)
{
p.drawPixmap(j*IMAGE_WIDHT,i*IMAGE_HEIGHT,IMAGE_WIDHT,IMAGE_HEIGHT,
QPixmap(QString(":/img/%0.png").arg(PixmapData[i][j])));
}
// 游戏结束
if(lab_data == 100 ){
// emit Win();
p.drawPixmap(10*10,10*10,300,300, QPixmap(":/img/win.jpeg"));
update();
if( win ==true){
p.drawPixmap(10*10,10*10,300,300, QPixmap(":/img/over.jpeg"));
update();
}
}
}
void start::setbol(){
win =true;
}
void start::newGame()
{
showGameArea=true;
update();
}
void start::initdate(){
showGameArea=false;
//生成的数据必须成对,可以先生成一半,后一半通过前一半得到
QVector<int>*hasExist=new QVector<int>(ROW_COUNT/2*COLUMN_COUNT,0);
for(int i=0;i<ROW_COUNT/2;++i)
for(int j=0;j<COLUMN_COUNT;++j){
int type=QRandomGenerator::global()->generate()%10;
//先生成前一半
PixmapData[i][j]=type;
//生成后一半
while(true)
{
//生成后一半的随机数 如 50~99
int tempIndex=QRandomGenerator::global()->generate()%(ROW_COUNT/2*COLUMN_COUNT)+
ROW_COUNT/2*COLUMN_COUNT;
//判断是否出现过 没有出现,则赋值
if((*hasExist)[tempIndex-ROW_COUNT/2*COLUMN_COUNT]==0)
{
PixmapData[tempIndex/ROW_COUNT][tempIndex%ROW_COUNT]=type;
(*hasExist)[tempIndex-ROW_COUNT/2*COLUMN_COUNT]=1;
break;
}
}
}
isEmpty=new QVector<QVector<bool>>(ROW_COUNT,QVector<bool>(COLUMN_COUNT,false));
clickCount=0;
firstClickX=-1;
firstClickY=-1;
}
void start:: mousePressEvent(QMouseEvent *e){
int currentX=e->x()/IMAGE_WIDHT;
int currentY=e->y()/IMAGE_HEIGHT;
//如果点击的图片是空,那就直接返回
if((*isEmpty)[currentY][currentX])
return ;
++clickCount;
//第一次点击
if(clickCount%2!=0)
{
firstClickX=currentX;
firstClickY=currentY;
qDebug()<<"第一次点击"<<firstClickY<<","<<firstClickX<<"图片类型是"<<PixmapData[currentY][currentX];
}
//如果是第二次点击
else if(clickCount%2==0){
qDebug()<<"第二次点击"<<currentY<<" ,"<<currentX<<"图片类型是"<<PixmapData[currentY][currentX];
//若图片类型不同或者点击位置相同直接return
if(PixmapData[firstClickY][firstClickX]!=PixmapData[currentY][currentX]||
(currentY==firstClickY&¤tX==firstClickX))
return ;
//判断是否可以连接
bool flag=canBeLinked(firstClickY,firstClickX,currentY,currentX);
qDebug()<<"判断连接"<<flag;
//可以 则first current对应的isEmpty修改为true
if(flag)
{
qDebug()<<"修改数组";
(*isEmpty)[firstClickY][firstClickX]=true;
(*isEmpty)[currentY][currentX]=true;
PixmapData[firstClickY][firstClickX] = -1;
PixmapData[currentY][currentX] = -1;
update();
start::lab_data += 2; //得分数
ui->label_sock->setText(QString("得分:%0").arg(lab_data));
}
}
}
//判断连接函数
bool start::canBeLinked(int row1, int col1, int row2, int col2)
{
return inOneLine(row1, col1, row2, col2)||inTwoLine(row1, col1, row2, col2)||inThreeLine(row1, col1, row2, col2);
}
bool start::inOneLine(int row1, int col1, int row2, int col2)
{
bool flag=true;
//在一条直线上 判断两点连线之间有没有物体存在
//行相同
if(row1==row2)
{
for(int i=qMin(col1,col2)+1;i<qMax(col1,col2);++i){
if(!(*isEmpty)[row1][i])
{
flag=false;
break;
}
}
if(flag)
return true;
}
//列相同
else if(col1==col2)
{
for(int i=qMin(row1,row2)+1;i<qMax(row1,row2);i++)
{
qDebug()<<i<<","<<col1<<" "<<(*isEmpty)[row1][i];
if(!(*isEmpty)[i][col1])
{
return false;
}
}
return true;
}
//都不相同直接返回false
return false;
}
bool start::inTwoLine(int row1, int col1, int row2, int col2)
{
//两点之间,构成的矩形,以左上和右下作为中转点判断一条直线
bool flag1=inOneLine(row1,col1,row1,col2)&&inOneLine(row1,col2,row2,col2);
bool flag2=inOneLine(row1,col1,row2,col1)&&inOneLine(row2,col1,row2,col2);
return ( flag1 && (*isEmpty)[row1][col2] ) || ( flag2 && (*isEmpty)[row2][col1] );
}
bool start::inThreeLine(int row1, int col1, int row2, int col2)
{
//以一点的横竖两轴每点作为中转点寻找路径
//选择点(row1,col1)
//先选择横轴,即固定行
bool flag=false;
for(int i=0;i<COLUMN_COUNT;i++)
{
if(i==col1)
continue;
if((*isEmpty)[row1][i]){
flag=inOneLine(row1,i,row1,col1)&&inTwoLine(row1,i,row2,col2);
}
if(flag)
return true;
}
//固定列
for(int i=0;i<ROW_COUNT;i++)
{
if(i==row1)
continue;
if((*isEmpty)[i][col1]){
flag=inOneLine(i,col1,row1,col1)&&inTwoLine(i,col1,row2,col2);
}
if(flag)
return true;
}
return false;
}
void start:: mouseReleaseEvent(QMouseEvent *event){
}
void start::on_pushButton_clicked()
{
//退出游戏
this->close();
}
线程代码
#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <QThread>
#include <start.h>
class mythread : public QThread
{
//申请需要信号与槽机制
Q_OBJECT
signals:
void valueChanged(int);//设置进度条的信号
void opvalue(int); //设置lcd的信号
void gameover(); //游戏结束
public:
mythread(int delay);
void run(){
for(int i = 100; i >= 0; i--){
for(int j=0; j<mydelay; j++);
emit valueChanged(i);
emit opvalue(i);
if(i == 0){
emit gameover();
}
}
}
int mydelay;
};
#endif // MYTHREAD_H
总结
因时间有限,该游戏只有简单功能,仅作为练习qt使用,望见谅!!!