AI-随机迷宫&迷宫求解

本文记录了,人工智能中简单的搜索策略中的路径搜索策略中的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-随机迷宫&迷宫求解

时间: 2024-12-11 15:26:16

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

Maze_AI: 一款基于 Python + Pygame + AI 算法的迷宫小游戏

大三课程设计周自己一个人写的迷宫小游戏 (一)课题内容 实现走迷宫. 主要功能为界面显示.上下左右键的响应以及当前步数统计. 通过该课题全面熟悉数组.字符串等的使用,掌握程序设计的基本方法及友好界面的设计. (二)课题要求 1. 基本要求 (1)游戏界面显示:迷宫地图.上下左右移动的特效. (2)动作选择:上下左右键对应于上下左右的移动功能,遇到障碍的处理. (3)得分统计功能:步数等. 2. 扩展要求 (1)用户数据管理. (2)设计一个自动走迷宫的程序,使得得到最短路径. (三)组队分工情况

canvas——随机生成迷宫

先上图. 效果 代码 随机生成迷宫要求任意两点都能够找到相同的路径,也就是说,迷宫是一个连通图.随机生成迷宫可以使用普里姆算法.广度优先算法.深度优先算法等实现.这里将使用普里姆算法通过生成最小数的方法,实现迷宫图. 初始迷宫 迷宫有路和墙,白色表示路,黑色表示墙.每一个格子代表一个顶点,这里一共有100个顶点,需要找出99条边,使顶点连接起来,也就是要打通99块墙. 迷宫使用二位数组保存,为迷宫指定路的行数和列数,生成初始数组. 普利姆算法不了解的话,可以参考这篇博客的解析. /* * thi

Unity_Dungeonize 随机生成迷宫

本文对随机生成迷宫的实现思路进行记录,其作用在于为游戏过程提供随机性以及节省开发周期,下面是Dungeonize的结构 随机迷宫的生成主要包括几个阶段 1.生成房间体结构,为墙体,自定义房间,自定义物体生成平台 1 for (var i = 0; i < room_count; i++) { 2 Room room = new Room (); 3 if (rooms.Count == 0) { 4 //初始房间生成玩家和任务事件监听 5 room.x = (int)Mathf.Floor (m

【统计学习】随机梯度下降法求解感知机模型

1. 感知机学习模型 感知机是一个二分类的线性分类问题,求解是使误分类点到超平面距离总和的损失函数最小化问题.采用的是随机梯度下降法,首先任意选取一个超平面w0和b0,然后用梯度下降法不断地极小化目标损失函数,极小化过程中不是一次使所有误分类点的梯度下降,而是一次随机选取一个误分类点使其梯度下降.假设误分类点集合M是固定的,那么损失函数L(w,b)的梯度: 随机选取一个误分类点,对w和b进行更新: 其中n是步长,又称为学习率(learning rate),这样通过迭代可以使损失函数L(w,b)不

随机梯度下降算法求解SVM

测试代码(matlab)如下: clear; load E:\dataset\USPS\USPS.mat; % data format: % Xtr n1*dim % Xte n2*dim % Ytr n1*1 % Yte n2*1 % warning: labels must range from 1 to n, n is the number of labels % other label values will make mistakes u=unique(Ytr); Nclass=len

栈实现迷宫求解(c++版)

相信大家都应该听过栈吧,一直想利用栈来实现一个算法,最近有点空,就利用栈的先进后出的特性来完成迷宫求的问题,下面将详细介绍栈的实现和迷宫求解的过程,可以很好的学习栈的使用. 栈有两种实现方法,一种是顺序,即数组形式,一种是线性,即链表形式,个人还是比较喜欢链表形式实现栈的基本功能. 首先弄一个简单的迷宫,如图: 我们很容易看出这个迷宫解的路径,那怎么让计算机帮我们求解出来呢. 首先我们要对迷宫数据化,很容易想到二维数组来表示,0表示通路,1表示障碍,即表示为: int map[4][4]={ {

遗传算法的应用(求解迷宫问题)

遗传算法(Genetic Algorithm): 是模拟达尔文生物进化论的自然选择和遗传学机理的生物进化过程的计算模型,是一种通过模拟自然进化过程搜索最优解的方法. 遗传算法是从代表问题可能潜在的解集的一个种群(population)开始的,而一个种群则由经过基因(gene)编码的一定数目的个体(individual)组成. 每个个体实际上是染色体(chromosome)带有特征的实体. 染色体作为遗传物质的主要载体,即多个基因的集合,其内部表现(即基因型)是某种基因组合,它决定了个体的形状的外

迷宫问题(输出路径)_友好界面_音乐播放_彩色字体

1 /* 2 8 6 3 1 1 1 1 1 1 1 1 4 1 0 0 1 0 0 1 1 5 1 1 0 0 0 0 0 1 6 1 0 0 1 0 1 0 1 7 1 0 0 0 0 0 0 1 8 1 1 1 1 1 1 1 1 9 */ 10 #include <iostream> //////////-static-libgcc 11 #include <iomanip> 12 #include <ctime> 13 #include <stack&g

[游戏开发-学习笔记]菜鸟慢慢飞(二)-迷宫

简介:练手Demo,<走出迷宫>,文章主要说说如何创建迷宫. 学习Unity3D有一段时间了,自己想了一个项目来练手手.然后就有了这篇. 一.固定的格数,开局后随机生成. 说明:这个迷宫10*10,开始后随机生成,四周留下一个空做出口. 先说如何实现: 主要准备了三个Prefab:横墙,竖墙,柱子,墙高度是10,宽度是10,厚度是1,柱子高度是10.宽度和厚度都是10. 手动按照10*10排列(参考下图) 脚本 #region //初始化游戏 #endregion using System.C