八数码难题也称九宫问题,它是在3×3的方格棋盘上,分别放置了表有数字1、2、3、4、5、6、7、8的八张牌,初始状态S0,目标状态Sg,要求程序能输入任意的初始状态和目标状态,要求通过空格来移动八张牌使得棋盘由初始状态到达目标状态。移动规则为:每次只能将与空格(上下左右)相邻的一个数字平移到空格中。
如下图所示,左侧为初始状态,右侧为目标状态
在开始求解之前,我们先判断该八数码问题是否有解,判断方法如下:
八数码问题的一个状态实际上是0~9的一个排列,空格用0表示,对于任意给定的初始状态和目标状态,不一定有解,也就是说从初始状态不一定能到达目标状态。因为排列有奇排列和偶排列两类,排列只能在同类排列之间转化,而从奇排列不能转化成偶排列或相反。
如果一个数字0~8的随机排列871526340,用F(X)表示数字X前面比它小的数的个数,全部数字的F(X)之和为Y=∑(F(X)),如果Y为奇数则称原数字的排列是奇排列,如果Y为偶数则称原数字的排列是偶排列。
例:871526340这个排列的Y=0+0+0+1+1+3+2+3+0=10,10是偶数,所以是偶排列。
871625340,Y=0+0+0+1+1+2+2+3+0=9,9是奇数,所以是奇排列。
因此,可以在运行程序前检查初始状态和目标状态的排列是否相同,相同则问题可解,接着采用搜索算法求解,否则无解。
我们可以采用广度优先算法来进行求解,大致流程如下
附上一部分代码,有兴趣的同学可以自己尝试
%查询是否找到目标节点
function a=getit(close,dis)
global i;
for j=1:i
if close(j).con==dis
a=1;
break;
else
a=0;
end
end
end
上下左右移动模块
function open=opera(op,cl,f,dis)
global i;
[x,y]=find(f.con==0);
if x==1&&y==1
open=rt(f,op,cl,dis);
open=dn(f,open,cl,dis);
elseif x==1&&y==2
open=lt(f,op,cl,dis);
open=rt(f,open,cl,dis);
open=dn(f,open,cl,dis);
elseif x==1&&y==3
open=lt(f,op,cl,dis);
open=dn(f,open,cl,dis);
elseif x==2&&y==1
open=up(f,op,cl,dis);
open=rt(f,open,cl,dis);
open=dn(f,open,cl,dis);
elseif x==2&&y==2
open=lt(f,op,cl,dis);
open=up(f,open,cl,dis);
open=rt(f,open,cl,dis);
open=dn(f,open,cl,dis);
elseif x==2&&y==3
open=lt(f,op,cl,dis);
open=up(f,open,cl,dis);
open=dn(f,open,cl,dis);
elseif x==3&&y==1
open=up(f,op,cl,dis);
open=rt(f,open,cl,dis);
elseif x==3&&y==2
open=lt(f,op,cl,dis);
open=up(f,open,cl,dis);
open=rt(f,open,cl,dis);
elseif x==3&&y==3
open=lt(f,op,cl,dis);
open=up(f,open,cl,dis);
end
end
查询重复操作模块
function []=search(f,op,cl)
global e;
global i;
%e
%open(e-1).con
for j=1:e-1
if op(j).con==f.con
e=e-1;
break
end
end
for j=1:i-1
if cl(j).con==f.con
e=e-1;
break;
end
end
end
最后附上不完全效果图
点击查看更多内容
为 TA 点赞
评论
共同学习,写下你的评论
评论加载中...
作者其他优质文章
正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦