AI-随机迷宫&迷宫求解

本文记录了,人工智能中简单的搜索策略中的路径搜索策略中的A*算法,来实现迷宫寻路的问题.(这只是一次本人的课外做业)html

完整的程序源码已经发送到个人Git.这里只记录了个人思路和感想以及收获.git


产生随机迷宫github

迷宫求解没有迷宫怎么能够呢.而本人是个懒人,每次都要手动输入迷宫,重复性的工做让我很不爽.你能够在程序中用数组定义一个迷宫啊,有强迫症的我,怎么能够这样随便的要求本身的程序呢.及时求解算法的出来了,可是测试数据有限,仍是让我很不爽的,因此,干脆先花一些时间,写个随机迷宫的产生吧.算法

遇事先搜索,看看前辈有没有经验分享,站在前辈的肩膀上,你能够少走不少弯路.编程

本人搜索到一篇论文:基于图的深度遍历产生随机迷宫的算法研究,看了之后,发现论文中有不少的错误,并且算法也不简洁,有不少地方彻底能够很是简化的,可是非要写的那么复杂,生怕别人能够看懂似得.因此,就按照本身的理解,简单的实现了随机迷宫的产生.数组

001

参考上图,红色(起始位置),绿色(终点位置).而我产生随机迷宫的方法简单,产生的迷宫有必定的局限性.如图所示,从起始位置(最左上角)开始,每次随机的选取当前节点的右边或下边的节点做为扩展的节点.顺便还要判断一下下一个结点是否越界.经过这种方法会产生一条从矩形的一个点到另外一个点的最短路径,该条路径是没有回路的路径,就这样,当随机选择出一条路径之后,其他的点任意摆布,是墙是路均可以,最终咱们必定会获得一条最短的路径,个人简单随机迷宫诞生了.dom

至于更加完善的随机迷宫的产生,之后有时间了再学习一下.函数


A*算法遍历学习

若是在这里介绍这个算法,我感受太没意思了.人工智能的学习仍是有视频或者专人的讲授比较好,看书真的很枯燥的.这里我只说实现的过程当中的困难和想法以及收获.测试

A*算法中重要的由2张表,open表和close表.

open表存放的都是没有扩展的节点,并且表里的内容(fn=gn+hn)是按照从小到大排序的。

close表存放的都是已经扩展过的节点,也就说已经遍历过的节点,这表里的节点中就存在着最终的路径。

A*算法先是利用open表和close表找到最终的目标节点,而后倒序从close表里依次把之前遍历过的路径节点找出来,便可获得完整的路径。

002

就想上图所示的简单迷宫同样,开始的时候,会同时扩展右边和下面的节点,存入open表里,而后选择open表中f最小的值,而在这个例子中,选择的是下面的方块,因此就这样沿着红色箭头的方向一直扩展下去,直到,发现open表中的2个节点有10和12,这时候,才调转方向,抛弃12,选择10((0,1)节点)继续开始新的遍历(蓝色箭头的方向),最终找到终点。

找到终点之后,图中的阴影的结点都在close表里面,而后,咱们发现路径中的g从终点到起点是倒序的,h则是升序的。咱们就利用这个特性来实现路径的输出。g=10的下一个节点的特征是(g=g-1&&节点是相邻的)根据这个判断,咱们就会很容易的倒序找到完整的路径了。详细的实现的方法参见代码。


个人收获

花费了一周的时间来实现这个功能,使用的C++语言,并且中间也遇到了很多的困难。当你遇到的困难实在想不起好的解决方法的时候,那么不妨先放下,作其余的事情.晚上睡觉的时候,或者吃放走路洗澡的时候,脑子里想一想就能够了.解决问题的关键是在一瞬间想起来的,实在不行的时候,不妨让大脑放松一下,没必要心急火燎,容易上火.

bug(1)

堆栈的溢出:之前写程序的时候没有遇到过这种问题,曾经都使用过上万的数据空间,也没有出现过问题,可是此次的二维数组QT上面使用23*23,也就是迷宫的长和宽就出现这种状况了。长和宽23*23,那么顶点总共529个,转化为边的关系则有529*529=279841,额,确实有点大。解决方法很简单,定义成全局变量或者结构里面使用指针,函数里面使用动态的malloc内存分配,就OK了。

bug(2)

01

翻译过来就是算数异常,这个bug直到如今我也没有解决,由于不妨碍我程序的运行,这个bug只在程序调试的时候才出现。以下:

02

你们知道程序调试的环境和运行的环境是不同的,就那Qt来讲吧,运行的时候MinGW,而调试的时候是GDB,根据图示,这里应该出现了k=0的状况,random产生的随机数的范围是0~k-1因此,出错了。我是这么想的,也可能错了,若有看法,请指点。关于此次的程序,使个人GDB也崩溃了,害得我还从新安装了QT。

bug(3)

03

参考资料这么说的:出现了Segmentation fault,基本上的缘由是,非法的内存访问。例如数组的越界,在循环操做时循环变量的控制问题,也有字符串拷贝时长度溢出,指针指向了非法的空间,还有就是申明一个指针,但却没有对其初始化,就直接引用,或者没有开辟内存空间就释放内存,因此要检查申请空间时间的成功。

编程习惯的改进:

说实话程序大了,代码多了,有时候就不在乎良好的编程习惯了。此次在遇到bug的时候,请教了QQ群的网友,虽然说最终的问题没有解决,可是,给我提了很多宝贵的建议。

(1)变量的使用和定义尽可能额紧凑,靠在一块儿。

(2)最重要的也就是这一句:不要在判断语句中使用有反作用的语句。何为反作用?会改变程序状态的语句。以下:

if(getchar()=='Y'||getchar()=='y')
{}

getchar()从缓冲区读取一个字符,读一个少一个,那么读的过程当中程序的状态是否是改变了?

好的写法以下:

char ch=toupper(getchar());
if('Y'==ch)
{}

学习的道路艰巨而漫长.

相关文章
相关标签/搜索