在宽度优先解决八数码问题基础上对节点类增加深度属性
import copy
import numpy as np
from datetime import datetime
# 字符串列表化
def string_to_ls(str):
return [i.split(' ') for i in str.split(',')]
# 获取位置
def get_loacl(arr, target):
# r, c = np.where(arr == target)
# return r, c
for i in arr:
for j in i:
if j == target:
return arr.index(i), i.index(j)
# 获取可以和0交换位置的元素
def get_elements(arr):
r, c = get_loacl(arr, '0')
elements = []
if r > 0:
elements.append(arr[r - 1][c]) # 上面的元素
if r < 2:
elements.append(arr[r + 1][c]) # 下边的元素
if c > 0:
elements.append(arr[r][c - 1]) # 左面的元素
if c < 2:
elements.append(arr[r][c + 1]) # 右面的元素
return elements
def get_child(arr, e):
# 深拷贝与浅拷贝!!
arr_new = copy.deepcopy(arr)
r, c = get_loacl(arr_new, '0')
r1, c1 = get_loacl(arr_new, e)
arr_new[r][c], arr_new[r1][c1] = arr_new[r1][c1], arr_new[r][c]
return arr_new
def is_goal(arr, goal):
return arr == goal
class state:
def __init__(self, state, deep, parent):
# state是一个3x3的ls矩阵
self.state = state
self.deep = deep
self.parent = parent
def chidren(self):
chidren = []
for i in get_elements(self.state):
child = state(state=get_child(self.state, i), deep=self.deep + 1, parent=self)
chidren.append(child)
return chidren
# 打印求解路径
def print_path(n):
if n.parent == None:
return
else:
print('↑')
print(np.array(n.parent.state))
print_path(n.parent)
if __name__ == '__main__':
# initial = '0 1 3,4 2 5,7 8 6'
# goal = '4 1 3,7 0 5,8 2 6'
# initial = '0 7 8,2 5 4,3 6 1'
# goal = '7 5 8,2 4 1,3 6 0'
initial = '4 0 1,6 8 5,7 3 2'
goal = '5 8 2,1 0 4,6 3 7'
initial_arr = state(string_to_ls(initial), deep=0, parent=None)
goal_arr = string_to_ls(goal)
start = datetime.now()
open = [initial_arr]
close = []
# limit = eval(input('请输入要搜索的深度:'))
limit = 20
while len(open) > 0:
open_tb = [i.state for i in open]
close_tb = [i.state for i in close]
n = open.pop(0)
close.append(n)
if is_goal(n.state, goal_arr):
print(np.array(n.state))
print_path(n)
print('求解过程如上')
break
else:
if n.deep < limit:
for i in n.chidren():
if i.state not in open_tb:
if i not in close_tb:
open.insert(0, i)
else:
print('该深度下无解')
end = datetime.now()
print('深度为{}下的搜索步数为:{}'.format(close[-1].deep, len(close) - 2))
print('共耗时:', end - start)