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 完成游戏 游戏失败后,无法再次完成游戏,只能重新开始一局 对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提交类型
说明:Git提交类型指的是代码commit时,写在comment前面的标志,表示此次commit的提交类型,如下: Git提交类型 常见的Git提交类型有: feat:新特性、新功能或优化; fix:修复…...
C++速通LeetCode简单第18题-杨辉三角(全网唯一递归法)
全网唯一递归法: 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作为单线程模型,为什么效率高、速度快呢?
前言: 效率高、速度快是相较于数据库来说的(MySQL、Orcale、SQL server) 文章目录 一、单线程模式的工作流程二、为什么快? 一、单线程模式的工作流程 这里我们所说的单线程是指:Redis只使用一个线程,来处…...
人工智能——猴子摘香蕉问题
一、实验目的 求解猴子摘香蕉问题,根据猴子不同的位置,求解猴子的移动范围,求解对应的过程,针对不同的目标状态进行求解。 二、实验内容 根据场景有猴子、箱子、香蕉,香蕉挂天花板上。定义多种谓词描述位置、状态等…...
对ViT 中Patch Embedding理解
借鉴了这个博主的ViT Patch Embedding理解-CSDN博客,再加了一些理解。 就通过代码来理解吧 假设输入图像的维度为HxWxC,分别表示高,宽和通道数。 PatchEmbed 的类,它继承了 nn.Module,实现了将输入的2维图像&#…...
Redis基本命令详解
1. 基本命令 命令不区分大小写,而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-(volatile) volatile不保证原子性 synchronized保证内存可见性 wait()和notify() wait()方法 notify() 理解notify()和notifyAll() wait和sleep的对比 volatile关键字 volati…...
计算机毕业设计之:基于微信小程序的校园流浪猫收养系统
博主介绍: ✌我是阿龙,一名专注于Java技术领域的程序员,全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师,我在计算机毕业设计开发方面积累了丰富的经验。同时,我也是掘金、华为云、阿里云、InfoQ等平台…...
SpringBoot:关于Redis的配置失效(版本问题)
我们使用redis时发现yaml配置中的redis相关配置不生效,后面发现将配置修改甚至删除所有相关redis的配置,springboot依然能使用redis里面默认的db0并且不报错。上网查阅了一些文章,也都没有解决今天分享下,我的处理方法, SpringBo…...
halcon 快速定义字典
定义一个名为params的字典 Params : dict{} 等价于用 create_dict (Params ) 为字典添加键值对,在halcon中箭只能是字符串,值可以是任何类型的obj或者tuple Params.remove_outer_edges : true Params.max_gap : 150 等价于用 set_dict_object (true,…...
Sublime text3怎么关闭提示更新
问题 sublime text 3有新版本后,会不停地在每次启动后弹窗提示更新版本 第一步 软件安装之前,切记是软件安装之前!!!需要在hosts中添加以下内容(屏蔽官网联网检测):hosts的位置一般在C:\Windows\System32\drivers\etc…...
生成式语言模型技术栈
生成式语言模型的最新技术栈正在快速发展,尤其是随着大规模预训练模型(LLMs)和生成式AI的应用不断扩展。以下是当今最前沿的生成式语言模型技术栈,涵盖从模型开发到优化、推理和部署的各个环节。 1. 基础模型开发 基础模型开发包…...
进程分析工具Process Explorer使用
进程分析工具Process Explorer使用 Process Explorer让使用者能了解看不到的在后台执行的处理程序,能显示目前已经载入哪些模块,分别是正在被哪些程序使用着,还可显示这些程序所调用的DLL进程,以及他们所打开的句柄。Process Expl…...
vue 中如何实现鼠标拖动出发滚动条的跟随移动?
使用场景 在做弹窗、表单或 tab 切换需求的时候,有时候因为内容过长会导致出现滚动条,但是只能拖动滚动条时会导致操作不便,我们会希望实现通过拖动内容区实现滚动条的滑动。这样操作就会简单多了。 实现思路 如果要实现鼠标辅助触发滚动条…...
【Java EE】文件IO
Author:MTingle major:人工智能 --------------------------------------- Build your hopes like a tower! 目录 一、文件是什么? 二、针对文件系统操作的API 1.文件路径,文件名,文件是否存在 2. 创建文件 3.删除文件&#…...
使用 React、Material-UI、Spring、MySQL、MyBatis 以及高德 API 模拟实时位置信息
要使用 React、Material-UI、Spring、MySQL、MyBatis 以及高德 API 模拟实时位置信息,你可以按以下步骤来实现: 目录 1. 前端 (React Material-UI) 2. 后端 (Spring Boot MyBatis MySQL) 3. 模拟实时位置数据 4. 前后端联调 1. 前端 (React Mat…...
UniApp一句话经验: px -> rpx动态转换和动态元素区域的获取
px->rpx转换 在多终端条件下,什么devicePixelRatio,upx2px都是不靠谱的,最直接的是这样: const { screenWidth } uni.getSystemInfoSync()const pixelUnit screenWidth / 750 // rpx->px比例基数 动态元素区域获取 多终…...
Python基于flask框架的智能停车场车位系统 数据可视化分析系统fyfc81
目录 技术栈和环境说明解决的思路具体实现截图系统设计python语言django框架介绍flask框架介绍性能/安全/负载方面可行性分析论证python-flask核心代码部分展示python-django核心代码部分展示技术路线操作可行性详细视频演示源码获取 技术栈和环境说明 结合用户的使用需求&…...
D3KeyHelper:暗黑3效率提升工具的全方位应用指南
D3KeyHelper:暗黑3效率提升工具的全方位应用指南 【免费下载链接】D3keyHelper D3KeyHelper是一个有图形界面,可自定义配置的暗黑3鼠标宏工具。 项目地址: https://gitcode.com/gh_mirrors/d3/D3keyHelper D3KeyHelper是一款开源的暗黑3鼠标宏工具…...
智能电动汽车芯片全景解析:从MCU到SoC的技术跃迁
1. 智能电动汽车的芯片革命:从机械控制到数字大脑 十年前打开汽车引擎盖,看到的是一堆机械部件和少量电子控制单元;现在掀开一辆特斯拉的"前备箱",映入眼帘的却是布满芯片的电路板。这个直观变化背后,是汽车…...
基于python开发的送货上门系统
目录同行可拿货,招校园代理 ,本人源头供货商功能模块划分技术实现要点扩展功能建议部署与维护项目技术支持源码获取详细视频演示 :文章底部获取博主联系方式!同行可合作同行可拿货,招校园代理 ,本人源头供货商 功能模块划分 用户管理模块 用户注册与登录…...
iptables实战指南:从链表关系到规则配置的完整解析
1. iptables基础概念与核心组件 第一次接触iptables时,我盯着那些复杂的规则配置看了整整一个下午。后来才发现,理解iptables的关键在于掌握它的"四表五链"架构。简单来说,iptables就像是一个多层安检系统,数据包要经过…...
医疗AI智能体:从数据到关怀人文设计:告别冰冷精准,构建有温度的诊疗交互.131
一、智能体的人文设计医疗AI智能体以大模型为核心,串联医学知识图谱、实体识别模块、风险评估模块、话术生成模块、伦理审核模块五大核心组件,最终实现精准医学判断 人性化交互的双重目标。而在医疗场景中,用户的核心需求从来不是单纯的数据…...
Phi-4-mini-reasoning真实案例:教育机构自动批题与答案生成应用
Phi-4-mini-reasoning真实案例:教育机构自动批题与答案生成应用 1. 教育场景中的智能批改需求 在教育培训行业,教师每天需要花费大量时间批改作业和试卷。传统的人工批改方式存在几个明显痛点: 时间成本高:一位数学老师批改50份…...
Pixel Fashion Atelier快速上手:非对称RPG菜单布局与像素按键交互详解
Pixel Fashion Atelier快速上手:非对称RPG菜单布局与像素按键交互详解 1. 项目概览 Pixel Fashion Atelier是一款基于Stable Diffusion与Anything-v5的图像生成工作站,它彻底改变了传统AI工具的界面设计理念。这款工具将复古日系RPG游戏的"明亮城…...
何时DCDC预降压+LDO二次线性稳压?
LDO 核心选型分界结论及优化要点核心选型分界结论以LDO输入输出压差ΔV为核心判断指标,结合输出功率、场景约束,通用选型规则如下:通用强制分界点:当ΔV≥2V,且输出功率≥100mW(对应你之前的5V转3V70mA工况…...
Lychee-rerank-mm在音乐推荐中的创新应用
Lychee-rerank-mm在音乐推荐中的创新应用 1. 引言 你有没有遇到过这样的情况:在音乐平台上听到一首很喜欢的歌,想找类似的音乐,但系统推荐的歌曲却总是差强人意?要么封面风格完全不搭,要么歌词主题南辕北辙ÿ…...
HUNYUAN-MT惊艳翻译效果:专业领域长文档翻译案例集
HUNYUAN-MT惊艳翻译效果:专业领域长文档翻译案例集 最近在尝试各种翻译工具时,我偶然间用到了HUNYUAN-MT 7B模型来处理一些工作上的专业文档。说实话,一开始没抱太大期望,毕竟专业翻译的门槛不低,尤其是那些充满术语和…...
