问题的引入与准备:
with open(r'number_shifts.txt','r')as f:
data=f.read()
g_dict_shifts=eval(data)
#补全代码-----end-------#
print("移动规则:\n"+str(g_dict_shifts))
Layout_order = 3 # 设置阶数(棋盘大小)
Layout_len = Layout_order*Layout_order
#补全代码-----begin-------#
srcLayout=input("请输入初始布局,如'013425786':")
destLayout=input("请输入目标布局,如'123456780':")
代码输出结果:
二、利用逆序值判断目标布局是否有解
def judge_process(srcLayout,destLayout):
#计算初始布局和目标布局的逆序数src和dest。
#补全代码-----begin-------#
srcLayout=srcLayout.strip('0')
destLayout=destLayout.strip('0')
s_length=len(srcLayout)
d_length=len(destLayout)
c=0
d=0
for i in range(s_length):
for j in range(i):
if srcLayout[j]>srcLayout[i]:
c=c+1
for i in range(d_length):
for j in range(i):
if destLayout[j]>destLayout[i]:
d=d+1
print('srcLayout的逆序值为:',c,'destLayout的逆序值为:',d)
#补全代码-----end-------#
#判断src和dest是否奇偶性一致
#补全代码-----begin-------#
if c%2==d%2:
print('src和dest的逆序值奇偶性一致')
else:
print('src和dest的逆序值奇偶性不一致')
return -1,None
judge_process(srcLayout,destLayout)
结果:
三、使用启发式算法实现位置移动:
# 启发式算法
# 返回srcLayout与destLayout两个布局中同一数字下标差之和,注意不计算数字0的下标差
def heuristic_algorithm(srcLayout,destLayout):
sum=0
#srcLayout与destLayout间的距离
#计算srcLayout与destLayout的距离
#补全代码-----begin-------#
for i in srcLayout:
if i=='0':
continue
else:
sum=sum+abs(srcLayout.index(i)-destLayout.index(i))
#补全代码-----end-------#
return sum
heuristic_algorithm(srcLayout,destLayout)
代码输出结果:
创建数字交换函数:
def swap_chr(nLayout, i, j, deep, destLayout):
# 实现i位置的数字与j位置的数字交换
#补全代码-----begin-------#
#方法一
nLayout=list(nLayout)
x=nLayout[j]
nLayout[j]=nLayout[i]
nLayout[i]=x
nLayout=','.join(nLayout)
nLayout=nLayout.replace(',','')
tmpLayout=nLayout
#方法二
# if i<j:
# tmpLayout=nLayout[:i]+nLayout[j]+nLayout[i:j]+nLayout[j+1:]
# else:
# tmpLayout=nLayout[:j]+nLayout[i]+nLayout[j:i]+nLayout[i+1:]
#补全代码-----end-------#
# 计算fn,f(n)=g(n)+h(n)
fn = heuristic_algorithm(tmpLayout, destLayout)+deep
return tmpLayout, fn
四、A*算法实现:
# A*算法过程
# stack_layouts = [] #存储所有可能的状态,OPEN表
# lst_steps = [] #最佳搜索路径
# g_dict_layouts={} #类似于CLOSED表,以字典形式存储,记录每个节点的父节点,以便当找到目标节点时能够快速定位实际的最短路径
# g_dict_layouts_deep = {}#以字典形式存放每个状态的gn值
# g_dict_layouts_fn = {}#OPEN表,以字典形式存放每个状态的fn值
# #初始化:初始状态的相关结果
# g_dict_layouts[srcLayout] = -1 #初始状态的父节点为-1(将初始状态加入了CLOSED表)
# g_dict_layouts_deep[srcLayout]= 0 #初始状态的深度(gn)值为0
# g_dict_layouts_fn[srcLayout] = g_dict_layouts_deep[srcLayout] + heuristic_algorithm(srcLayout, destLayout)
# # 将当前状态存入OPEN表(stack_layouts)
# stack_layouts.append(srcLayout)
g_dict_layouts = {}
g_dict_layouts_deep = {}
g_dict_layouts_fn = {}
def solvePuzzle_A(srcLayout, destLayout):
src=0;dest=0
for i in range(1,9):
fist=0
for j in range(0,i):
if srcLayout[j]>srcLayout[i] and srcLayout[i]!='0':
fist=fist+1
src=src+fist
for i in range(1,9):
fist=0
for j in range(0,i):
if destLayout[j]>destLayout[i] and destLayout[i]!='0':
fist=fist+1
dest=dest+fist
if (src%2)!=(dest%2):
return -1, None
g_dict_layouts[srcLayout] = -1
g_dict_layouts_deep[srcLayout]= 1
g_dict_layouts_fn[srcLayout] = 1 + heuristic_algorithm(srcLayout, destLayout)
stack_layouts = []
gn=0
stack_layouts.append(srcLayout)
while len(stack_layouts) > 0:
curLayout = min(g_dict_layouts_fn, key=g_dict_layouts_fn.get)
del g_dict_layouts_fn[curLayout]
stack_layouts.remove(curLayout)
if curLayout == destLayout:
break
ind_slide = curLayout.index("0")
lst_shifts = g_dict_shifts[ind_slide]
for nShift in lst_shifts:
newLayout, fn = swap_chr(curLayout, nShift, ind_slide, g_dict_layouts_deep[curLayout] + 1, destLayout)
if g_dict_layouts.get(newLayout) == None:
g_dict_layouts_deep[newLayout] = g_dict_layouts_deep[curLayout] + 1
g_dict_layouts_fn[newLayout] = fn
g_dict_layouts[newLayout] = curLayout
stack_layouts.append(newLayout)
lst_steps = []
lst_steps.append(curLayout)
while g_dict_layouts[curLayout] != -1:
curLayout = g_dict_layouts[curLayout]
lst_steps.append(curLayout)
lst_steps.reverse()
return 0, lst_steps
# A*算法搜索过程
srcLayout=input("请输入初始布局,如'013425786':")
destLayout=input("请输入目标布局,如'123456780':")
liu, lst_steps = solvePuzzle_A(srcLayout, destLayout)
if liu != 0:
print("目标布局不可达")
else:
for i in range(len(lst_steps)):
print("step #" + str(i + 1))
print(lst_steps[i][:3])
print(lst_steps[i][3:6])
print(lst_steps[i][6:])
print('当前布局为:',lst_steps[i][:3]+lst_steps[i][3:6]+lst_steps[i][6:])
输出结果:
到这里就基本上没有什么问题了,大家如果有什么问题都可以私信问我喔!
也可以关注我的公众号:风程序员
谢谢大家的关注!