学习要学会举一反三。在以前的《用matlab扫扫雷》一文中,我用matlab简单的编写了一个扫雷小程序。当然,与Windows自带的扫雷程序自然是不敢相提并论。今天我就用c++来写个扫雷程序,算是对c++的练习。在那篇文章中提过,扫雷问题是NP完全问题,不能被解决。网上也有人做过扫雷的辅助工具,但也只是指明肯定是雷、和肯定不是雷的位置,不能完全求解。下面来讲述我的程序设计思路:
1.用随机数生成雷分布的矩阵,元素为0表示无雷,1表示有雷。
2.通过循环遍历来统计一个元素的周围与之相邻的8个元素的雷的个数。
3.当鼠标左击某个按钮时,如果有雷则游戏失败。如果没有雷且其周围8个位置雷的个数为0,则将周围的8个位置打开,如果这8个位置中还有元素的周围8个元素个数为0,则将它周围的8个位置打开,依次类推……。知道将所有雷都标记正确,游戏胜利。

游戏的缺点:
1.由于时间关系,没有对游戏的界面进行美化,因此界面比较简陋。
2.与Windows自带的扫雷相比,少了几点功能,如果学了QML可能效果会好一点,但是不影响正常使用。
3.没有对代码进行优化,代码可能显得冗余。

在编写过程中想到的:卷积的妙用
        在统计一个元素与之相邻的8个元素的雷的总个数的时候,一般最容易想到的是用遍历来统计:
    int x1,x2,x3,x4,x5,x6,x7,x8;//分别表示周围的8个位置的行
    int y1,y2,y3,y4,y5,y6,y7,y8;//分别表示周围的8个位置的列
    int count=0;//统计雷的个数
    for(row=0;row<9;row++)
        for(col=0;col<9;col++)
        {
            x1=row-1;y1=col-1;
            x2=row-1;y2=col;
            x3=row-1;y3=col+1;

            x4=row;y4=col-1;
            x5=row;y5=col+1;

            x6=row+1;y6=col-1;
            x7=row+1;y7=col;
            x8=row+1;y8=col+1;

            if(x1>=0&&y1>=0)//需要判断行和列是否越界
                if( minefield[x1][y1]==1)
                    count=count+1;

            if(x2>=0)
                if( minefield[x2][y2]==1)
                         count=count+1;

            if (x3>=0&&y3<9)
                if (minefield[x3][y3]==1)
                     count=count+1;

            if (y4>=0)
                if (minefield[x4][y4]==1)
                     count=count+1;

            if (y5<9)
                if (minefield[x5][y5]==1)
                     count=count+1;

            if(x6<9&&y6>=0)
                if (minefield[x6][y6]==1)
                     count=count+1;

            if(x7<9)
                if (minefield[x7][y7]==1)
                     count=count+1;
            if(x8<9&&y8<9)
                if( minefield[x8][y8]==1)
                     count=count+1;
            countnum[row][col]=count;
            count=0;

        }

上面的程序通俗易懂,但是需要经过多次的条件判断来保证数组的下标不越界。在matlab中我们可以通过一条语句则可以解决上述问题。

看下面的例子:

上图中,a就是雷的分布矩阵,1表示雷区。b是我们自己设置的一个特殊矩阵。c就是我们需要得到的雷的个数的矩阵,其中的含义如下:
c[0][0]=2,表示以a[0][0]为中心的九宫格中的雷的个数(自己的没有算在内)。那么c是如何得到的呢?正如上面所说,只需要一条命令即可:c=conv2(a,b,'same')。也就是求a矩阵和b矩阵的卷积!
当然矩阵的卷积我们在《信号与线性系统分析》中没有讲到,但是书中提到了一维向量的卷积。例如:
a=[1 2 3];  b=[4 5 6];
则a与b的卷积为c=conv(a,b)=[ 4    13    28    27    18];
具体的计算过程可以通过公式计算,下面用比较简单的方法来计算上面的卷积


上面的计算方法和小学学的乘法好像一样,在我印象中,两个信号这样求卷积的前提好像是这两个信号都是因果信号,唉,具体是什么条件我也不是很清楚了。在这里来说,就不用管这些条件限制。
矩阵的卷积归根到底可以转换成一维向量的卷积,具体的做法是(以第一次的例子的值为例):首先,将一个矩阵选择180度,这里我们选择b矩阵,碰巧b矩阵选择后的矩阵b1和原矩阵b一样;然后将b1矩阵每次往下移一行,将b1与a矩阵在同一行的一行分别进行一维向量的卷积运算,然后对应的列相加起来合并为一行。具体过程图解如下:

     conv([1 0 1],[1 1 1])=[ 1     1     2     1     1]

conv([1 0 1],[1 0 1])+conv([1 1 1],[1 1 1])= [2     2     5     2     2]

conv([1 0 1],[1 1 1])+conv([1 1 1],[1 0 1])+conv([0 1 1],[1 1 1])= [2  3  6  4  3]

conv([1 1 1],[1 1 1])+conv([0 1 1],[1 0 1])=[  1     3     4     3     2]

conv([0 1 1],[1 1 1])= [0     1     2     2     1]

 综上所述:a与b的卷积是     
     1     1     2     1     1
     2     2     5     2     2
     2     3     6     4     3
     1     3     4     3     2
     0     1     2     2     1

这与c=conv2(a,b)的结果相同!而在我的扫雷程序中想要得到的是与a相同维数的矩阵,因此我们可以使用 c=conv2(a,b,'same')来得到我们的结果。

在前面的讨论中,我们使用的b矩阵是b=[1 1 1;1 0 1;1 1 1]。b的选取与我要的结果有关,如果我需要的是九宫格中所有的雷的个数(包含中心格) ,我们可以令b=[1 1 1;1 1 1;1 1 1];验证结果如下:

如果我们选择b=[1 1 1;1 1 0;1 1 1],那么相当于不把中心格右边的雷计算在内,验证如下:
 
到目前为止,其中的规律就不言而喻了。
不知不觉一天就过去了,导师的报告还没写,就此搁笔。

由于扫雷程序的代码较多,在此只是讲解了大概思路,具体代码见本文末尾的链接,代码有比较详尽的注释
 程序运行截图如下:
1.开始的界面:

2.输了的界面:

3.赢了的界面:
 




程序下载请访问: http://pan.baidu.com/s/1kzntk

原文:http://blog.csdn.net/tengweitw/article/details/23378983

作者:nineheadedbird

【Qt编程】Qt版扫雷的更多相关文章

  1. Qt编程简介与基本知识

    1. 什么是Qt? Qt是一个基于C++的跨平台应用程序和UI开发框架.它包含一个类库,和用于跨平台开发及国际化的工具. 由挪威Trolltech公司开发,后被Nokia收购,目前被Digia公司收购 ...

  2. 学习 Qt 编程的好书精品推荐!

    最近一段时间,准备开始搞Qt方面的东西,想找几本书看看.网上介绍QT的书籍也有很多,不想浪费时间,所以想找几本精品的书籍来看.花了半天的时间找了几本非常不错的,这里面整理好之后推荐给大家! 下面介绍的 ...

  3. qt编程入门

    面对qt编程,必须先知道qt中常用的类: QPushButton按钮类.QLabel标签类.QMessageBox对话框类.QCheckBox.QAction.QMenu.QStatusBar.QTo ...

  4. Visual Studio下Qt编程中对中文的处理

    Visual Studio下Qt编程中对中文的处理 本文为原创文章,原文地址http://www.cnblogs.com/c4isr/p/qt_develop_in_vs.html Visual St ...

  5. QT笔记(1)--QT编程环境搭建

    一.QT简介 Qt  是一个1991年由奇趣科技开发的跨平台C++图形用户界面应用程序开发框架.它既可以开发GUI程序,也可用于开发非GUI程序,比如控制台工具和服务器.Qt是面向对象的框架,使用特殊 ...

  6. Qt编程学习网站

    http://blog.csdn.net/k122769836/article/details/8637677 QT - little_su - 博客频道 - CSDN.NET Qt - 1+1=2 ...

  7. 在windows下的QT编程中的_TCHAR与QString之间的转换

    由于在windows下的QT编程中,如果涉及到使用微软的API,那么不可避免使用_TCHAR这些类型,因此在网上查了一下,其中一个老外的论坛有人给出了这个转换,因此在这里做一下笔记 : )#ifdef ...

  8. QT编程环境搭建

    使用QT需要QT的库以及QT creator,在QT5以后的版本中,两者已经集成,不需要单独下载了,只需要下载一个文件即可.配置步骤如下: 1.下载qt-opensource-windows-x86- ...

  9. 【Qt编程】基于Qt的词典开发系列<五>--无边框窗口的拖动

    在上一篇文章中,我们讲述了如何进行无边框窗口的缩放与拖动,而在一些情况下,我们的窗口只需要进行拖动也不需要改变其大小,比如:QQ的登录窗口.本来在上一篇文章中已经讲述了如何进行窗口的拖动,但是却与窗口 ...

  10. Qt编程之悲惨世界

    最近需要给人写点基于QtWebkit的代码,算是领教了Qt编程的痛苦之处. QNetworkConfigurationManager::isOnline() 只有在编译平台上能运行,拷贝到其他Wind ...

随机推荐

  1. webpack2 配置 示例

    // https://github.com/webpack-contrib/extract-text-webpack-plugin var webpack = require("webpac ...

  2. Bootstrap3 排版-对齐

    通过文本对齐类,可以简单方便的将文字重新对齐. Left aligned text. Center aligned text. Right aligned text. Justified text. ...

  3. MyBatis批量新增和更新

    之前有开发任务一个接口里面有大量的数据新增和更新操作,导致十分缓慢.使用了批量操作之后速度有明显提升,几乎百倍千倍的速度提升. 博主之前统计过,通过普通接口一次数据库插入大概需要200ms,对于大量新 ...

  4. CDH 5.x 集群安装及卸载

    上次写了CDH安装测试总结,由于那个博客篇幅略长, 但是主要集中在第二章,所以单独把CDH安装.卸载这块的内容拉出来在一篇记录一下. 一.搭建远程yum源 1.启动http服务: service ht ...

  5. Android样式(style)和主题(theme)

    样式和主题 样式是指为 View 或窗口指定外观和格式的属性集合.样式可以指定高度.填充.字体颜色.字号.背景色等许多属性. 样式是在与指定布局的 XML 不同的 XML 资源中进行定义. Andro ...

  6. Google Dremel数据模型详解(上)

    首先简单介绍一下Dremel是什么,能解决什么问题.第二部分着重讲Dremel的数据模型,即数据结构.第三部分将谈一下在此数据结构上设计的算法. 1 起源 Dremel的数据模型起源于分布式系统的应用 ...

  7. memcached实战系列(五)Memcached: List all keys 查询所有的key

    memcached可能当时设计的时候就把它定位为内存性的kv结构的缓存系统.所以没有持久化到磁盘的命令,也没有查看所有key的值得命令.可能觉得没必要吧,你要是缓存1个G内存的数据,自己都头大,还敢看 ...

  8. Java中for_each循环的使用

    最近在看一些和安卓相关的书籍,看到了for_each这种循环结构,这是为了简化java的for循环而改造的一种方便使用的格式. 格式如下: for(数据类型 变量:集合) 语句块 接下来看一个例程: ...

  9. 【美工设计 - Adobe Illustrator】基本设置 (图像显示 | 图像缩放 | 置入导出 | 标尺 | 网格 | 参考线 | 画板)

    作者 : 韩曙亮 转载请注明出处 : http://blog.csdn.net/shulianghan/article/details/50232767 一. 基础操作 1. 设置图像显示效果 (1) ...

  10. "ORA-20100: 为 FND_FILE 创建文件 o0003167.tmp 失败"

     今天在运行请求时候得到如下的错误日志: 原因:由于ORA-20100:为FND_FILE创建文件o0003167.tmp失败. 在请求日志的错误原因中您会找到更详细的信息. 查找了一些资料,总结 ...