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

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


产生随机迷宫

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

遇事先搜索,看看前辈有没有经验分享,站在前辈的肩膀上,你可以少走很多弯路.

本人搜索到一篇论文:基于图的深度遍历产生随机迷宫的算法研究,看了以后,发现论文中有很多的错误,而且算法也不简洁,有很多地方完全可以非常简化的,但是非要写的那么复杂,生怕别人可以看懂似得.所以,就按照自己的理解,简单的实现了随机迷宫的产生.

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

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


A*算法遍历

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

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

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

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

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

就想上图所示的简单迷宫一样,开始的时候,会同时扩展右边和下面的节点,存入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)

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

大家知道程序调试的环境和运行的环境是不一样的,就那Qt来说吧,运行的时候MinGW,而调试的时候是GDB,根据图示,这里应该出现了k=0的情况,random产生的随机数的范围是0~k-1所以,出错了。我是这么想的,也可能错了,如有见解,请指点。关于这次的程序,使我的GDB也崩溃了,害得我还重新安装了QT。

bug(3)

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

编程习惯的改进:

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

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

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

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

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

好的写法如下:

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

学习的道路艰巨而漫长.


AI-随机迷宫&迷宫求解的更多相关文章

  1. canvas——随机生成迷宫

    先上图. 效果 代码 随机生成迷宫要求任意两点都能够找到相同的路径,也就是说,迷宫是一个连通图.随机生成迷宫可以使用普里姆算法.广度优先算法.深度优先算法等实现.这里将使用普里姆算法通过生成最小数的方 ...

  2. Unity_Dungeonize 随机生成迷宫

    本文对随机生成迷宫的实现思路进行记录,其作用在于为游戏过程提供随机性以及节省开发周期,下面是Dungeonize的结构 随机迷宫的生成主要包括几个阶段 1.生成房间体结构,为墙体,自定义房间,自定义物 ...

  3. 【Javascript + Vue】实现随机生成迷宫图片

    前言 成品预览:https://codesandbox.io/s/maze-vite-15-i7oik?file=/src/maze.js 不久前写了一篇文章介绍了如何解迷宫:https://www. ...

  4. [ C语言 ] 迷宫 迷宫生成器 [ 递归与搜索 ]

    [原创]转载请注明出处 [浙江大学 程序设计专题] [地图求解器] 本题目要求输入一个迷宫地图,输出从起点到终点的路线. 基本思路是从起点(Sx,Sy)每次枚举该格子上下左右四个方向,直到走到终点(T ...

  5. 关于Unity中AI随机巡逻障碍物预判与快速运动时物理穿透的思考

    如果不想用Unity的导航系统,很多时候就要解决如何预判前进路径中的障碍物问题,之前也看过一些非常经典的寻路算法例如AStar寻路,虽然也可实现功能,但总感觉有些小题大做.寻路算法大多数都是为了得出最 ...

  6. 机器学习---用python实现最小二乘线性回归算法并用随机梯度下降法求解 (Machine Learning Least Squares Linear Regression Application SGD)

    在<机器学习---线性回归(Machine Learning Linear Regression)>一文中,我们主要介绍了最小二乘线性回归算法以及简单地介绍了梯度下降法.现在,让我们来实践 ...

  7. AI 随机梯度下降(SGD)

    随机梯度下降(stochastic gradient descent) 梯度是期望 计算梯度耗时太长

  8. 随机梯度下降算法求解SVM

    测试代码(matlab)如下: clear; load E:\dataset\USPS\USPS.mat; % data format: % Xtr n1*dim % Xte n2*dim % Ytr ...

  9. 迷宫问题求解之“A*搜索”(二)

    摘要:在迷宫问题求解之"穷举+回溯"(一)这篇文章中采用"穷举+回溯"的思想,虽然能从迷宫的入口到出口找出一条简单路径,但是找出来的不是最优路径.因此本文采用A ...

随机推荐

  1. freeCodeCamp:Falsy Bouncer

    真假美猴王! 删除数组中的所有假值. 在JavaScript中,假值有false.null.0."".undefined 和 NaN. /*思路 利用布尔值构造filter的测试函 ...

  2. Config文件的读写

    using System; using System.Configuration; using System.Xml; namespace COMMON { public class ConfigHe ...

  3. 【Java学习笔记】Map接口的子接口---TreeMap

    TreeMap,与TreeSet类似,可以对集合中的元素进行排序,同时保持元素的唯一性. 应注意,Comparable(实现接口,记得覆盖comparaTo方法),Comparator的使用. imp ...

  4. UWP的拖拽功能

    简单的拖拽实现: <Grid x:Name="G1" AllowDrop="True" DragEnter="G1_DragEnter" ...

  5. 猜数字 事先给定一个数字,然后让用户猜3次,猜不中就输了,猜中就赢了。 每次猜错,给出提示,less or big

    c = 0a = 10while c <3:    b = int(raw_input("请输入数字"))    if b == a:        print " ...

  6. PHP对象转数组||PHP数组转对象

    function arrayToObject($e){     if( gettype($e)!='array' ) return;     foreach($e as $k=>$v){     ...

  7. XAF ListView 移除顶部工具栏

    此方法适用于C/S及B/S,无需分别写在web和win中. Module下新建ViewController,代码如下: public partial class GongZuoJiaoShen_Yin ...

  8. Matlab-Octave中绘制网格图和等高线:mesh 和 surf

    x=linspace(-50, 50, 50); % 在x轴上取50点y=linspace(-25, 25, 25); % 在y轴上取25点[xx,yy]=meshgrid(x, y); % xx和y ...

  9. UDP及其组播,接收发送封装

    1.Receiver public class Receiver { public delegate void HeartBeat(byte[] data); public event HeartBe ...

  10. Request三种获取数据的方式

    今天在做ajax请求后台代码时,发现ajax的方法都对,但就是请求不了后台代码,后来在同事帮助下才发现前台定义了两个相同参数导致请求出错. 下面记录一下request三种获取数据的方式: 1. Req ...