一、初始化
global olen; %open表的长度
global clen; %close表的长度
global time; %循环次数
clen=0;
olen=1;
time=0;
target=input("请输入目标状态(以三阶方阵表示):");
%% 节点结构体
node.pre=zeros(3);
node.cur=input("请输入初始状态(以三阶方阵表示):");
node.num=1;
node.value=cost(node,target);
node.step=0;
openList(1)=node; %初始化open表
label=0; %循环停止标志
k=node; %临时节点
二、代价评估函数
cost.m
function value=cost(node,target)
choice=2;
%% 计算当前状态与目标状态八个数字的曼哈顿距离之和
if choice==1
distance=0;
for i=1:8
[x,y]=find(node.cur==i);
[x1,y1]=find(target==i);
distance=distance+abs(x-x1)+abs(y-y1);
end
value=distance;
end
%% 计算错位数个数
if choice==2
count=0;
count=sum(sum(node.cur~=target));
value=count;
end
end
%% 计算欧式距离
if choice==3
distance=0;
for i=1:8
[x,y]=find(node.cur==i);
[x1,y1]=find(target==i);
distance=distance+power(x-x1,2)+power(y-y1,2);
end
value=distance;
end
三、空格的移动操作
move.m
%% 移动操作,九个位置对应九种情况
function openList=move(op,cl,node,target)
global clen;
[x,y]=find(node.cur==0);
if x==1&&y==1
openList=right(node,op,cl,target);
openList=down(node,openList,cl,target);
elseif x==1&&y==2
openList=left(node,op,cl,target);
openList=right(node,openList,cl,target);
openList=down(node,openList,cl,target);
elseif x==1&&y==3
openList=left(node,op,cl,target);
openList=down(node,openList,cl,target);
elseif x==2&&y==1
openList=up(node,op,cl,target);
openList=right(node,openList,cl,target);
openList=down(node,openList,cl,target);
elseif x==2&&y==2
openList=left(node,op,cl,target);
openList=up(node,openList,cl,target);
openList=right(node,openList,cl,target);
openList=down(node,openList,cl,target);
elseif x==2&&y==3
openList=left(node,op,cl,target);
openList=up(node,openList,cl,target);
openList=down(node,openList,cl,target);
elseif x==3&&y==1
openList=up(node,op,cl,target);
openList=right(node,openList,cl,target);
elseif x==3&&y==2
openList=left(node,op,cl,target);
openList=up(node,openList,cl,target);
openList=right(node,openList,cl,target);
elseif x==3&&y==3
openList=left(node,op,cl,target);
openList=up(node,openList,cl,target);
end
end
%% 向右移动
function openList=right(node,op,cl,target)
global olen;
olen=olen+1;
s=node;
[x,y]=find(s.cur==0);
t=s.cur(x,y+1);
s.cur(x,y+1)=0;
s.cur(x,y)=t;
s.num=olen;
op(olen).cur=s.cur;
op(olen).pre=node.cur;
op(olen).num=olen;
op(olen).value=cost(s,target);
op(olen).step=s.step+1;
search(s,op,cl);
openList=op;
end
%% 向上移动
function openList=up(node,op,cl,target)
global olen;
olen=olen+1;
s=node;
[x,y]=find(s.cur==0);
t=s.cur(x-1,y);
s.cur(x-1,y)=0;
s.cur(x,y)=t;
s.num=olen;
op(olen).cur=s.cur;
op(olen).pre=node.cur;
op(olen).num=olen;
op(olen).value=cost(s,target);
op(olen).step=s.step+1;
search(s,op,cl);
openList=op;
end
%% 向左移动
function openList=left(node,op,cl,target)
global olen;
olen=olen+1;
s=node;
[x,y]=find(s.cur==0);
t=s.cur(x,y-1);
s.cur(x,y-1)=0;
s.cur(x,y)=t;
s.num=olen;
op(olen).cur=s.cur;
op(olen).pre=node.cur;
op(olen).num=olen;
op(olen).value=cost(s,target);
op(olen).step=s.step+1;
search(s,op,cl);
openList=op;
end
%% 向下移动
function openList=down(node,op,cl,target)
global olen;
olen=olen+1;
s=node;
[x,y]=find(s.cur==0);
t=s.cur(x+1,y);
s.cur(x+1,y)=0;
s.cur(x,y)=t;
s.num=olen;
op(olen).cur=s.cur;
op(olen).pre=node.cur;
op(olen).num=olen;
op(olen).value=cost(s,target);
op(olen).step=s.step+1;
search(s,op,cl);
openList=op;
end
四、查重操作
search.m
%% 查找并去除状态重复的节点
function []=search(node,op,cl)
global olen;
global clen;
for i=1:olen-1
if op(i).cur==node.cur
olen=olen-1;
break;
end
end
for i=1:clen-1
if cl(i).cur==node.cur
olen=olen-1;
break;
end
end
end
五、主函数
main.m
global olen; %open表的长度
global clen; %close表的长度
global time; %循环次数
clen=0;
olen=1;
time=0;
%target=input("请输入目标状态(以三阶方阵表示):");
target=[0,1,2;3,4,5;6,7,8];
%% 节点结构体
node.pre=zeros(3);
%node.cur=input("请输入初始状态(以三阶方阵表示):");
node.cur=[1,2,3;4,5,6;7,8,0];
node.num=1;
node.value=cost(node,target);
node.step=0;
openList(1)=node; %初始化open表
label=0; %循环停止标志
k=node; %临时节点
tic
while label==0
time=time+1;
%% 寻找代价最小的节点
for i=1:olen
if (k.value+k.step)>=(openList(i).value+openList(i).step)
k=openList(i);
x=i;
end
end
%% 访问过的节点加入close表
clen=clen+1;
closeList(clen)=k;
closeList(clen).num=clen;
%% 判断是否找到目标节点
label=min(min(k.cur==target));
%% 扩展节点并删除open表中已访问的节点
openList=move(openList,closeList,k,target);
k.value=inf;
openList(x)=[];
olen=olen-1;
end
toc
%% 存储路径
b=0;
n=0;
y=target;
while 1
for i=1:clen
if y==zeros(3)
b=1;
break;
end
if closeList(i).cur==y
t=closeList(i).num;
n=n+1;
index(n)=t;
y=closeList(i).pre;
end
end
if b==1
break;
end
end
%% 打印结果
fprintf('求解成功,共用步数:%d',size(index,2)-1);
disp(" ");
disp("最佳路径为:")
for i=1:n
if i==1
disp("开始:")
else
fprintf("第");
fprintf('%d',i-1);
fprintf("步:");
disp(" ");
end
disp(closeList(index(n+1-i)).cur);
end
———2021.3.3(gzc)