当前位置: 首页 > 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();
}
 

相关文章:

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

有三种难度初级6x6 中级10x10 高级16x16 完成游戏 游戏失败后&#xff0c;无法再次完成游戏&#xff0c;只能重新开始一局 对Qpushbutton进行重写 mybutton.h #ifndef MYBUTTON_H #define MYBUTTON_H #include <QObject> #include <QWidget> #include <QPus…...

09.20 C++对C的扩充以及C++中的封装、SeqList

SeqList.h #ifndef SEQLIST_H #define SEQLIST_H#include <iostream> #include<memory.h> #include<stdlib.h> #include<string.h>using namespace std;//typedef int datatype; //类型重命名 using datatype int;//封装一个顺序表 class Seq…...

Git提交类型

说明&#xff1a;Git提交类型指的是代码commit时&#xff0c;写在comment前面的标志&#xff0c;表示此次commit的提交类型&#xff0c;如下&#xff1a; Git提交类型 常见的Git提交类型有&#xff1a; feat&#xff1a;新特性、新功能或优化&#xff1b; fix&#xff1a;修复…...

C++速通LeetCode简单第18题-杨辉三角(全网唯一递归法)

全网唯一递归法&#xff1a; vector<vector<int>> generate(int numRows) {vector<int> v;vector<vector<int>>vn;if (numRows 1){v.push_back(1);vn.push_back(v);v.clear();return vn;//递归记得return}if (numRows 2){v.push_back(1);vn.p…...

Redis作为单线程模型,为什么效率高、速度快呢?

前言&#xff1a; 效率高、速度快是相较于数据库来说的&#xff08;MySQL、Orcale、SQL server&#xff09; 文章目录 一、单线程模式的工作流程二、为什么快&#xff1f; 一、单线程模式的工作流程 这里我们所说的单线程是指&#xff1a;Redis只使用一个线程&#xff0c;来处…...

人工智能——猴子摘香蕉问题

一、实验目的 求解猴子摘香蕉问题&#xff0c;根据猴子不同的位置&#xff0c;求解猴子的移动范围&#xff0c;求解对应的过程&#xff0c;针对不同的目标状态进行求解。 二、实验内容 根据场景有猴子、箱子、香蕉&#xff0c;香蕉挂天花板上。定义多种谓词描述位置、状态等…...

对ViT 中Patch Embedding理解

借鉴了这个博主的ViT Patch Embedding理解-CSDN博客&#xff0c;再加了一些理解。 就通过代码来理解吧 假设输入图像的维度为HxWxC&#xff0c;分别表示高&#xff0c;宽和通道数。 PatchEmbed 的类&#xff0c;它继承了 nn.Module&#xff0c;实现了将输入的2维图像&#…...

Redis基本命令详解

1. 基本命令 命令不区分大小写&#xff0c;而key是区分大小写的 # select 数据库间的切换 数据库共计16个 127.0.0.1:6379> select 1# dbsize 返回当前数据库的 key 的数量 127.0.0.1:6379[1]> dbsize# keys * 查看数据库所有的key 127.0.0.1:6379[1]> keys *# fl…...

Java之线程篇四

目录 volatile关键字 volatile保证内存可见性 代码示例 代码示例2-&#xff08;volatile&#xff09; volatile不保证原子性 synchronized保证内存可见性 wait()和notify() wait()方法 notify() 理解notify()和notifyAll() wait和sleep的对比 volatile关键字 volati…...

计算机毕业设计之:基于微信小程序的校园流浪猫收养系统

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…...

SpringBoot:关于Redis的配置失效(版本问题)

我们使用redis时发现yaml配置中的redis相关配置不生效&#xff0c;后面发现将配置修改甚至删除所有相关redis的配置&#xff0c;springboot依然能使用redis里面默认的db0并且不报错。上网查阅了一些文章&#xff0c;也都没有解决今天分享下&#xff0c;我的处理方法, SpringBo…...

halcon 快速定义字典

定义一个名为params的字典 Params : dict{} 等价于用 create_dict (Params ) 为字典添加键值对&#xff0c;在halcon中箭只能是字符串&#xff0c;值可以是任何类型的obj或者tuple Params.remove_outer_edges : true Params.max_gap : 150 等价于用 set_dict_object (true,…...

Sublime text3怎么关闭提示更新

问题 sublime text 3有新版本后,会不停地在每次启动后弹窗提示更新版本 第一步 软件安装之前&#xff0c;切记是软件安装之前&#xff01;&#xff01;&#xff01;需要在hosts中添加以下内容(屏蔽官网联网检测)&#xff1a;hosts的位置一般在C:\Windows\System32\drivers\etc…...

生成式语言模型技术栈

生成式语言模型的最新技术栈正在快速发展&#xff0c;尤其是随着大规模预训练模型&#xff08;LLMs&#xff09;和生成式AI的应用不断扩展。以下是当今最前沿的生成式语言模型技术栈&#xff0c;涵盖从模型开发到优化、推理和部署的各个环节。 1. 基础模型开发 基础模型开发包…...

进程分析工具Process Explorer使用

进程分析工具Process Explorer使用 Process Explorer让使用者能了解看不到的在后台执行的处理程序&#xff0c;能显示目前已经载入哪些模块&#xff0c;分别是正在被哪些程序使用着&#xff0c;还可显示这些程序所调用的DLL进程&#xff0c;以及他们所打开的句柄。Process Expl…...

vue 中如何实现鼠标拖动出发滚动条的跟随移动?

使用场景 在做弹窗、表单或 tab 切换需求的时候&#xff0c;有时候因为内容过长会导致出现滚动条&#xff0c;但是只能拖动滚动条时会导致操作不便&#xff0c;我们会希望实现通过拖动内容区实现滚动条的滑动。这样操作就会简单多了。 实现思路 如果要实现鼠标辅助触发滚动条…...

【Java EE】文件IO

Author&#xff1a;MTingle major:人工智能 --------------------------------------- Build your hopes like a tower! 目录 一、文件是什么&#xff1f; 二、针对文件系统操作的API 1.文件路径&#xff0c;文件名&#xff0c;文件是否存在 2. 创建文件 3.删除文件&#…...

使用 React、Material-UI、Spring、MySQL、MyBatis 以及高德 API 模拟实时位置信息

要使用 React、Material-UI、Spring、MySQL、MyBatis 以及高德 API 模拟实时位置信息&#xff0c;你可以按以下步骤来实现&#xff1a; 目录 1. 前端 (React Material-UI) 2. 后端 (Spring Boot MyBatis MySQL) 3. 模拟实时位置数据 4. 前后端联调 1. 前端 (React Mat…...

UniApp一句话经验: px -> rpx动态转换和动态元素区域的获取

px->rpx转换 在多终端条件下&#xff0c;什么devicePixelRatio&#xff0c;upx2px都是不靠谱的&#xff0c;最直接的是这样&#xff1a; const { screenWidth } uni.getSystemInfoSync()const pixelUnit screenWidth / 750 // rpx->px比例基数 动态元素区域获取 多终…...

Python基于flask框架的智能停车场车位系统 数据可视化分析系统fyfc81

目录 技术栈和环境说明解决的思路具体实现截图系统设计python语言django框架介绍flask框架介绍性能/安全/负载方面可行性分析论证python-flask核心代码部分展示python-django核心代码部分展示技术路线操作可行性详细视频演示源码获取 技术栈和环境说明 结合用户的使用需求&…...

海外服务器哪个速度最快且性能稳定

海外服务器的速度与性能稳定性受多种因素影响&#xff0c;包括地理位置、网络架构、基础设施质量以及用户网络路径等。在众多选择中&#xff0c;几个特定地区的服务器因其卓越表现而备受推崇。 首先&#xff0c;美国硅谷(加利福尼亚州)与纽约的服务器以其技术领先、网络连接稳定…...

C/C++通过CLion2024进行Linux远程开发保姆级教学

目前来说&#xff0c;对Linux远程开发支持相对比较好的也就是Clion和VSCode了&#xff0c;这两个其实对于C和C语言开发都很友好&#xff0c;大可不必过于纠结使用那个&#xff0c;至于VS和QtCreator&#xff0c;前者太过重量级了&#xff0c;后者更是不用说&#xff0c;主要用于…...

工程师 - 如何安装Windows 终端

Windows 终端是一款适用于 Windows 的现代命令行应用程序&#xff0c;支持多个终端会话&#xff0c;包括 Command Prompt、PowerShell 和 Windows Subsystem for Linux (WSL)。它具有标签式界面、可定制的设置&#xff08;如主题和按键绑定&#xff09;、改进的文本渲染以及对 …...

UniApp 从Vue2升级为Vue3需要注意哪些方面

Vue官方已经发布了Vue3&#xff0c;Vue2不再维护&#xff0c;也在建议大家都迁移到Vue3&#xff0c;所以Vue2终会被淘汰。 那么UniApp 从Vue2升级为Vue3需要注意哪些方面&#xff1a; 1、main.js 下面请看创建应用实例Vue2与Vue3的不同&#xff1a; Vue2的写法&#xff1a;…...

前端面试CSS常见题目

1. CSS 选择器的优先级 (Specificity) 面试官通常会问你如何计算 CSS 选择器的优先级&#xff0c;这对于避免样式冲突、提高代码可维护性很重要。 优先级计算规则&#xff1a; !important 优先级最高。内联样式&#xff08;例如&#xff1a;<div style"color: red;&…...

408算法题leetcode--第10天

643. 子数组最大平均数 I 643. 子数组最大平均数 I思路&#xff1a;滑动窗口时间&#xff1a;O(n)&#xff1b;空间&#xff1a;O(1) class Solution { public:double findMaxAverage(vector<int>& nums, int k) {double ret 0, temp 0;size_t size nums.size()…...

13年计算机考研408-数据结构

解析&#xff1a; 这个降序链表不影响时间复杂度&#xff0c;因为是链表&#xff0c;所以你想要升序就使用头插法&#xff0c;你想要降序就使用尾插法。 然后我们来分析一下最坏的情况是什么样的。 因为m和n都是两个有序的升序序列。 如果刚好m的最大值小于n的最小值&#xff0…...

跨平台开发新视角:利用Android WebView实现Web内容的原生体验

在移动应用开发领域&#xff0c;跨平台解决方案一直是一个热门话题。开发者们不断寻求能够同时在iOS和Android平台上提供一致用户体验的方法。而Android的WebView组件&#xff0c;作为一个强大的工具&#xff0c;允许开发者在Android应用中嵌入Web内容&#xff0c;为用户提供接…...

Stable Diffusion 使用详解(11)--- 场景ICON制作

目录 背景 controlNet 整体描述 Canny Lineart Depth 实际使用 AI绘制需求 绘制过程 PS打底 场景模型选择 设置提示词及绘制参数 controlnet 设置 canny 边缘 depth 深度 lineart 线稿 效果 背景 这段时间不知道为啥小伙伴似乎喜欢制作很符合自己场景的ICON。…...

【Linux系统编程】第二十弹---进程优先级 命令行参数 环境变量

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】【C详解】【Linux系统编程】 目录 1、进程优先级 2.1、什么是优先级 2.2、优先级的描述 2.3、优先级与权限的关系 2.4、为什么要有优先级 2.5、Linux优先级的…...