Qt项目__连连看

本文档介绍了使用Qt进行UI开发的连连看项目,详细展示了游戏的开始界面和游戏界面,并提供了相关代码实现,包括窗口类和线程类的代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

项目介绍

项目展示:
界面1:

界面1

界面2:

界面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&&currentX==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使用,望见谅!!!
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值