当前位置: 首页 > news >正文

2024/9/20 使用QT实现扫雷游戏

有三种难度初级6x6 中级10x10  高级16x16

 

完成游戏

游戏失败后,无法再次完成游戏,只能重新开始一局

对Qpushbutton进行重写

mybutton.h

#ifndef MYBUTTON_H
#define MYBUTTON_H

#include <QObject>
#include <QWidget>
#include <QPushButton>
#include <QMouseEvent>
class mybutton : public QPushButton
{
    Q_OBJECT
public:
    mybutton(QWidget *parent = nullptr);
    void set_value(int hang,int lie);
    //重写鼠标点击事件
protected:
    virtual void    mouseReleaseEvent(QMouseEvent * event);

    //定义两个信号
signals:
    void LeftClicked(int hang,int lie);
    void RightClicked(int hang,int lie);

private:
    int lie;
    int hang;
};

#endif // MYBUTTON_H
 

mybutton.c

#include "mybutton.h"

 mybutton::mybutton(QWidget *parent):
    QPushButton(parent)
{

}

 void mybutton::mouseReleaseEvent(QMouseEvent * event)
 {
     //判断是鼠标左键点击还是右键点击
     if(event->button() ==  Qt::LeftButton)
     {//左键点击了
         emit LeftClicked(hang,lie);
     }
     if(event->button() ==  Qt::RightButton)
     {//右键点击了
         emit RightClicked(hang,lie);
     }
 }
void mybutton::set_value(int hang,int lie)
{
    this->hang=hang;
    this->lie=lie;
}
 

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QTimer>
#include "mybutton.h"
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

#define Lei 10 //设置雷占格子的多少

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
    void time_out(void);
    int GetThisMine(int hang,int lie,int i,int j);
    void Initbutton(int i,int j);
    void clear_button(int i,int j);
    //定义两个槽函数 用于处理按键左右键点击的信号
public slots:
   void LeftClickedSlots(int hang,int lie);
   void RightClickedSlots(int hang,int lie);
   void on_pushButton_clicked();
   void on_pushButton_2_clicked();
   void on_pushButton_4_clicked();
   void on_pushButton_3_clicked();

private slots:
   void on_pushButton_5_clicked();

private:
    Ui::Widget *ui;
    QTimer *tm1;
    int i,j;
    mybutton *Buttons;
    bool *mine;
    int flag=0;
    int s=0;
    int win=0;
};
#endif // WIDGET_H
 

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include "QDebug"
#include <QThread>
#include <QMessageBox>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    tm1 = new QTimer(this);
    //2,绑定定时器时间到槽
    connect(tm1, &QTimer::timeout, this,&Widget::time_out);
    //3.启动定时器
    tm1->start(1000); //定时器时间1000ms
    ui->lcdNumber->display(100);
    this->setWindowTitle("扫雷");
    //设置布局框大小
    ui->gridLayoutWidget->resize(this->size());
    ui->gridLayoutWidget->move(0,0);
}

Widget::~Widget()
{
    delete ui;
    delete []mine;
    delete []Buttons;
}

void Widget::time_out()
{
    //qDebug()<< "定时器时间到";
    int num = ui->lcdNumber->value();
    num -= 1;
    if(num==0)
        tm1->stop(); //停止定时器
    ui->lcdNumber->display(num);
}
void Widget::Initbutton(int i,int j)
{   this->i=i;
    this->j=j;
    Buttons =new mybutton[i*j];
    for(int hang = 0; hang <i; hang++)
        for(int lie =0; lie < j; lie++)
        {
            Buttons[hang*j+lie].set_value(hang,lie);
            Buttons[hang*j+lie].setSizePolicy(QSizePolicy::Preferred,QSizePolicy::Preferred);
            //将按钮放到布局中
            ui->gridLayout->addWidget(&Buttons[hang*j+lie], hang+1, lie);
            ui->gridLayout->setRowStretch(hang,0);
            ui->gridLayout->setColumnStretch(lie,0);
            //绑定信号和槽
            connect(&Buttons[hang*j+lie], &mybutton::LeftClicked, this, &Widget::LeftClickedSlots);
            connect(&Buttons[hang*j+lie], &mybutton::RightClicked, this, &Widget::RightClickedSlots);
        }
    //摇雷 ((i*j)/4)个
    srand(time(0));
    mine = new bool[i*j];
    for(int k=0;k<i*j;k++) mine[k]=false;
    for(int k=0;k<((i*j)/Lei);k++)
    {
        while(1){
            int h = rand() % i;
            int l = rand() % j;
            if(!mine[h*j+l])
            {//此处没有雷
                mine[h*j+l] = true;
                break;
            }
        }
    }
//    for(int h=0;h<i*j;h++)
//        qDebug()<<mine[h];
    }
void Widget::clear_button(int i,int j)
{
    for(int hang = 0; hang <i; hang++)
        for(int lie =0; lie < j; lie++)
            ui->gridLayout->removeWidget(&Buttons[hang*j+lie]);
    delete []Buttons;
    s=0;
    win=0;
}

void Widget::on_pushButton_clicked()//低级难度
{
    switch(flag)
    {
    case 0:Initbutton(6,6);break;
    case 1:clear_button(6,6);Initbutton(6,6);break;
    case 2:clear_button(10,10);Initbutton(6,6);break;
    case 3:clear_button(16,16);Initbutton(6,6);break;
    default: qDebug()<<"游戏未开始";
    }
    flag=1;
}


void Widget::on_pushButton_2_clicked()//中级难度
{
    switch(flag)
    {
    case 0:Initbutton(10,10);break;
    case 1:clear_button(6,6);Initbutton(10,10);break;
    case 2:clear_button(10,10);Initbutton(10,10);break;
    case 3:clear_button(16,16);Initbutton(10,10);break;
    default: qDebug()<<"游戏未开始";
    }
    flag=2;
}

void Widget::on_pushButton_4_clicked()//高级难度
{
    switch(flag)
    {
    case 0:Initbutton(16,16);break;
    case 1:clear_button(6,6);Initbutton(16,16);break;
    case 2:clear_button(10,10);Initbutton(16,16);break;
    case 3:clear_button(16,16);Initbutton(16,16);break;
    default: qDebug()<<"游戏未开始";
    }
    flag=3;
}

void Widget::on_pushButton_3_clicked()//重玩
{
    switch(flag)
    {
    case 1:clear_button(6,6);Initbutton(6,6);break;
    case 2:clear_button(10,10);Initbutton(10,10);break;
    case 3:clear_button(16,16);Initbutton(16,16);break;
    default: qDebug()<<"游戏未开始";
    }
}
void Widget::LeftClickedSlots(int hang,int lie)//左击
{
    int n=i,m=j;
    qDebug() << "左键点击:" << hang << lie;
    Buttons[hang*m+lie].setCheckable(true);
    Buttons[hang*m+lie].setChecked(true); //显示为按键按下
    Buttons[hang*m+lie].setDisabled(true); // 按键不能交互
    ui->gridLayoutWidget->update();
    qDebug() << "按键锁定:";
    //显示周围有多少雷
    if(GetThisMine(hang,lie,n,m)==-1){
        Buttons[hang*m+lie].setText(QString::number(-1));
        QMessageBox::information(nullptr, "游戏失败", "恭喜你踩了一个雷");
    }
    //int cnt = GetThisMine(hang,lie,n,m);
    //Buttons[hang*m+lie].setText(QString::number(cnt));

}

void Widget::RightClickedSlots(int hang,int lie)//右击
{
    int n=i,m=j;
    qDebug() << "右键点击:" << hang << lie;
    //标记是雷
    QIcon icon(":/1.png");//使用资源包,相对路径
    if(Buttons[hang*m+lie].icon().isNull())
    {
    Buttons[hang*m+lie].setIcon(icon);
    qDebug()<<n;
    Buttons[hang*m+lie].setIconSize(QSize(Buttons[hang*m+lie].size().width()-20,
                                    Buttons[hang*m+lie].size().height() -20));
    win++;
    if(win==i*j) QMessageBox::information(nullptr, "游戏胜利", "恭喜你完成了游戏");
    return;
    }
    if(!Buttons[hang*m+lie].icon().isNull())
        Buttons[hang*m+lie].setIcon(QIcon());
    win--;

}

//计算hang,lie位置有多少雷
int Widget::GetThisMine(int hang,int lie,int n,int m)
{
    if(mine[hang*m+lie]==true) return -1;
    int cnt = 0;
    for(int i=-1; i<= 1; i++)
        for(int j=-1; j<=1; j++)
        {
            if(  !(i==0 && j==0) )
            {//排除自己
                if( hang+i < 0 || hang+i >= n || lie+j >= m || lie+j < 0 )
                    continue; //排除越界
                if(mine[(hang+i)*m+lie+j]) cnt ++;
            }
        }
    QThread::msleep(50);
    if(s==n*m) return cnt;
    qDebug() << "当前有值:"<<cnt<< s++<<endl;
    Buttons[hang*m+lie].setText(QString::number(cnt));
    Buttons[hang*m+lie].setCheckable(true);
    Buttons[hang*m+lie].setChecked(true); //显示为按键按下
    Buttons[hang*m+lie].setDisabled(true); // 按键不能交互
    ui->gridLayoutWidget->update();
    win++;
    if(win==i*j) QMessageBox::information(nullptr, "游戏胜利", "恭喜你完成了游戏");
    if(cnt==0)
    {
        //四个方向 左 上 右 下
        if(lie-1>=0&&Buttons[hang*m+lie-1].text().isEmpty()){
            qDebug() << "左连:";
            GetThisMine(hang,lie-1,n,m);
        }
        if(hang-1>=0&&Buttons[(hang-1)*m+lie].text().isEmpty()){
            qDebug() << "上连:";
            GetThisMine(hang-1,lie,n,m);
        }
        if(lie+1<m&&Buttons[hang*m+lie+1].text().isEmpty()){
            qDebug() << "右连:";
            GetThisMine(hang,lie+1,n,m);
        }
        if(hang+1<n&&Buttons[(hang+1)*m+lie].text().isEmpty()){
            qDebug() << "下连:";
            GetThisMine(hang+1,lie,n,m);
        }
        //四个角落 左上 右上 左下 右下
        if(hang-1>=0&&lie-1>=0&&Buttons[(hang-1)*m+lie-1].text().isEmpty()){
            qDebug() << "左上连:";
            GetThisMine(hang-1,lie-1,n,m);
        }
        if(hang-1>=0&&lie+1<m&&Buttons[(hang-1)*m+lie+1].text().isEmpty()){
            qDebug() << "右上连:";
            GetThisMine(hang-1,lie+1,n,m);
        }
        if(hang+1<n&&lie-1>=0&&Buttons[(hang+1)*m+lie-1].text().isEmpty()){
            qDebug() << "左下连:";
            GetThisMine(hang+1,lie-1,n,m);
        }
        if(hang+1<n&&lie+1<m&&Buttons[(hang+1)*m+lie+1].text().isEmpty()){
            qDebug() << "右下连:";
            GetThisMine(hang+1,lie+1,n,m);
        }
    }
    return cnt;
}

void Widget::on_pushButton_5_clicked()
{
    //设置布局框大小
    ui->gridLayoutWidget->resize(this->size());
    ui->gridLayoutWidget->move(0,0);
}
 

main.c

#include "widget.h"

#include <QApplication>

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

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 基于Vue 3组合函数的分页、搜索与排序实践 —— nbsaas-boot项目的实际应用
  • 4. 密码协议
  • 一站式语音识别服务:中文、方言、多语言全覆盖
  • vue node node-sass sass-loader 版本 对应 与 兼容
  • 进程间的通信-信号量
  • 【网络安全】-ssrf服务器请求伪造攻击-burp
  • 如何将Git本地代码推送到Gitee云端仓库
  • 使用 Bedrock 模型进行 SQL 查询生成:高效自动化的全新体验!
  • 【nodejs环境】nvm是真有用
  • PyQt5库学习之QFileDialog.getOpenFileName函数
  • 【Linux庖丁解牛】—Linux基本指令(上)!
  • LED 生产电子看板实现工厂精准管理
  • 本地搭建我的世界服务器(JAVA)简单记录
  • 【测试岗面试】知识点总结
  • 前端JavaScript导出excel,并用excel分析数据,使用SheetJS导出excel
  • [case10]使用RSQL实现端到端的动态查询
  • 【407天】跃迁之路——程序员高效学习方法论探索系列(实验阶段164-2018.03.19)...
  • React Transition Group -- Transition 组件
  • STAR法则
  • vue从创建到完整的饿了么(11)组件的使用(svg图标及watch的简单使用)
  • 复习Javascript专题(四):js中的深浅拷贝
  • 记一次和乔布斯合作最难忘的经历
  • 力扣(LeetCode)56
  • 名企6年Java程序员的工作总结,写给在迷茫中的你!
  • 如何设计一个比特币钱包服务
  • 深入浅出webpack学习(1)--核心概念
  • 我看到的前端
  • 以太坊客户端Geth命令参数详解
  • 微龛半导体获数千万Pre-A轮融资,投资方为国中创投 ...
  • ​Distil-Whisper:比Whisper快6倍,体积小50%的语音识别模型
  • ​第20课 在Android Native开发中加入新的C++类
  • ​软考-高级-信息系统项目管理师教程 第四版【第14章-项目沟通管理-思维导图】​
  • # 利刃出鞘_Tomcat 核心原理解析(八)-- Tomcat 集群
  • #162 (Div. 2)
  • #pragma multi_compile #pragma shader_feature
  • #我与Java虚拟机的故事#连载15:完整阅读的第一本技术书籍
  • (3)llvm ir转换过程
  • (c语言+数据结构链表)项目:贪吃蛇
  • (rabbitmq的高级特性)消息可靠性
  • (搬运以学习)flask 上下文的实现
  • (论文阅读26/100)Weakly-supervised learning with convolutional neural networks
  • (十)Flink Table API 和 SQL 基本概念
  • (四)activit5.23.0修复跟踪高亮显示BUG
  • (算法)求1到1亿间的质数或素数
  • .bat批处理(三):变量声明、设置、拼接、截取
  • .gitignore文件—git忽略文件
  • .mkp勒索病毒解密方法|勒索病毒解决|勒索病毒恢复|数据库修复
  • .naturalWidth 和naturalHeight属性,
  • .net mvc 获取url中controller和action
  • .net web项目 调用webService
  • .xml 下拉列表_RecyclerView嵌套recyclerview实现二级下拉列表,包含自定义IOS对话框...
  • @JsonFormat 和 @DateTimeFormat 的区别
  • @NoArgsConstructor和@AllArgsConstructor,@Builder
  • [ SNOI 2013 ] Quare
  • [20150904]exp slow.txt