A*算法实现8数码问题(c语言实现)

实验报告

【实验名称】
  A*算法实现8数码问题

【实验要求】
  在一个3 ×3的方格棋盘上放置着1到8八个数码,每个数码占一个,且有一个空格。这些数码可在棋盘上移动,其移动规则是:与空格相邻的数码方可移入空格。现在问题是:对于指定的初始棋局和目标棋局,给出数码移动序列。

  • 初始状态:用户任意给定

  • 目标状态
    1 2 3
    8   4
    7 6 5

【实验内容】
  算法思想:A*算法
  设S0 :初态, Sg:目标状态

  1. open={S0};
  2. closed={ };
  3. 如果open={},失败退出;
  4. 在open表上取出f最小的结点n, n放到closed表中;
  5. 若n∈Sg,则成功退出;
  6. 产生n的一切后继,将后继中不是n的先辈点的一切点构成集合M
  7. 对M中的元素P,分别作两类处理:
    7.1 若P不在open表和closed表中,配上指向n的返回指针后放入open表中;
    7.2 若P在open表或closed表中,修改open表或closed表中该节点及其后裔的返回指针和f(x)值,修改原则是“抄f(x)值小的路走”;
  8. 转3。

【实验结果图】

  • 主要代码及思路展示
    数据结构如下:注意要是指一个指向父节点的指针,为后续输出以及寻找最佳路径做备份。
    A*算法实现8数码问题(c语言实现)_第1张图片

  • 求解各棋子不在正确位置的数目
    A*算法实现8数码问题(c语言实现)_第2张图片

  • 求解估价函数

  • 空格的上下左右移动
    A*算法实现8数码问题(c语言实现)_第3张图片

  • 移动父节点并加入未探索表中(扩展结点)–其中一部分代码
    A*算法实现8数码问题(c语言实现)_第4张图片

  • 对OPEN表进行排序,插入法排序(按f从小到大)

A*算法实现8数码问题(c语言实现)_第5张图片

  • 头插法将最后的链表逆序
    A*算法实现8数码问题(c语言实现)_第6张图片

  • 主函数进行判断----最多循环次数1000,否则判断找不到最佳路径

A*算法实现8数码问题(c语言实现)_第7张图片
A*算法实现8数码问题(c语言实现)_第8张图片

  • 结果如下:
    可以找到路径的:
    A*算法实现8数码问题(c语言实现)_第9张图片
    A*算法实现8数码问题(c语言实现)_第10张图片
  • 无法找到路径的

A*算法实现8数码问题(c语言实现)_第11张图片

【实验小结】
   本次实验采用A算法解决八数码问题,我的思路是先构造两个结构体封装初始节点(要注意封装该节点的父节点,因为要输出最终的节点转移过程,所以必须要记录每一个节点是由哪一个节点扩展来的)以及OPEN、CLOSED状态表,然后用f=g+h来判断接下来该走哪一步。其中f 是节点n从初始点到目标点的估价函数,g 是在状态空间中从初始节点到n节点的实际代价,h是从n到目标节点最佳路径的估计代价。
  OPEN表保存所有已生成而未考察的节点,每次需要得到所有待扩展结点中f 值最小的那个结点,在将新产生的节点插入到OPEN表中时,需要对OPEN表进行排序,我采用插入法排序(按f从小到大);CLOSED表中记录已访问过的节点,存储已扩展的结点间的扩展关系,主要用于输出路径,CLOSED表的结构比较特殊,如果从头到尾顺序看是一个单向链表,从尾向前看是一个倒向的树。最后最后是将最后的节点输出,但是却是逆序输出的,所以我又定义了一个具有头结点的链表,采用头插法将链表逆序,输出结果的过程输出的这条路径线,即找到最终节点后,采用头插法倒置链表,从而正向输出结果。
  首先是将初始节点加入OPEN表,然后取出OPEN表的第一个节点,同时删除,加入CLOSED表,然后将该节点进行上下左右扩展,要同时满足该节点存在且移动后不存在重复的节点且该节点不在CLOSED和OPEN表中,将符合要求的节点加入OPEN表,不符合的节点要释放掉;再将OPEN表进行排序。重复以上步骤,直至OPEN表中取出的节点为目标节点则最终目标完成,将目标节点逆序找到最终的路径。同时要注意,可能最终没有找到结果,所以为了节省时间,需要设置条件当CLOSED表的长度length>1000时,即可大约认为无解。
  实验中遇到的问题主要有以下几个:首先节点和链表的初始化,由于本次实验我采用C语言编程,再分配内存空间时,不能直接将其分配s_g=(pnode) malloc(sizeof(node)),需要放在初始化函数中;还有就是将生成的新节点加入OPEN表时,并不能直接将节点赋值给链表的一个节点,需要设置一个copy_node(pnode s1,pnode s2)函数,将结构体里的每一个数值一一赋值;加入open表的条件需要考虑全面,要同时满足该节点存在且移动后不存在重复的节点且该节点不在CLOSED和OPEN表中,最后这两个条件忘记了导致OPEN表总是出现重复。
  这就是整个实验的思路及解决过程,通过写出解决该问题的代码,对于A
算法也有了更进一步的了解。

实验代码见如下:
https://download.csdn.net/download/qq_39373811/15704513

你可能感兴趣的:(实验报告,算法)