描述過幾天再寫,先放代碼
#!/usr/bin/python
# -*- coding: utf-8 -*-
'''
啓發式:heuristic
1、判斷從初始狀態到目標狀態是否有解
八數碼問題的一個狀態實際上是0~9的一個排列,空格用0表示,對於任意給定的初始狀態和目標狀態,不一定有解
因爲排列有奇排列和偶排列兩類,排列只能在同類排列之間轉化,而從奇排列不能轉化成偶排列或相反
'''
list_init = [] # 初始狀態
list_goal = [] # 目標狀態
open_list = []
close_list = []
path_list = {}
global scope
scope = 0
class Step:
def __init__(self,step_list,value):
self.step_list = step_list
self.value = value
def re_sort(): # open_list的數據重新排序
step_list = []
num_temp = len(open_list)
for k in range(num_temp):
list_temp1 = open_list.pop()
step_list.append(Step(list_temp1,height_match(list_temp1)))
step1 = sorted(step_list,key=lambda step:step.value)
for k in range(len(step1)):
open_list.append(step1[k].step_list)
def ji_ou(list0): # 判斷奇偶排列
time = 0
for i in range(len(list0)):
for j in range(len(list0)):
if i > j:
if list0[i] > list0[j]:
time += 1
else:
break
#return time
if time % 2 == 0:
return 2 # 偶排列
else:
return 1 # 奇排列
def is_res(): # 判斷是否有解
if ji_ou(list_init) != ji_ou(list_goal):
return False # 無解
else:
return True # 有解
def height_match(list_temp1): # 估值函數
return match_eight(list_temp1) + height_eight(list_temp1)
def height_eight(list_temp1): # 該點的深度
n = path_list[hund_list(list_temp1)] #該點的父節點
if n == hund_list(list_init):
return 1
else:
return 1 + height_eight(re_back(n))
def match_eight(list_temp1): # 相同位置“不在位”數量:h(n)
count = 0
for j in range(len(list_temp1)):
if list_temp1[j] != list_goal[j]:
count += 1
return count
def hund_list(list_cha): # 轉換爲數字
sum = 0
n = len(list_cha)
for j in range(n):
sum += ((list_cha[j] + 1) * (10 ** (n - j - 1)))
return sum
def re_back(n): # 將數字復原成list
list_pp = []
while n != 0:
list_pp.append((n % 10) - 1)
n = n // 10
list_pp.reverse()
return list_pp
def is_join(list_child, n,fa_list):
if (list_child not in open_list) & (list_child not in close_list):
open_list.append(list_child)
path_list[hund_list(list_child)] = n
if list_child in open_list:
if height_eight(list_child) > (height_eight(fa_list) + 1):
path_list[hund_list(list_child)] = n
if list_child in close_list:
if height_eight(list_child) > (height_eight(fa_list) + 1):
path_list[hund_list(list_child)] = n
close_list.remove(list_child)
open_list.append(list_child)
def change_list(list_one):
print("---------------------------------------------------")
print(str(list_one[0]) + ' ' + str(list_one[1]) + ' ' + str(list_one[2]))
print(str(list_one[3]) + ' ' + str(list_one[4]) + ' ' + str(list_one[5]))
print(str(list_one[6]) + ' ' + str(list_one[7]) + ' ' + str(list_one[8]))
def print_list(n):
global scope
scope += 1
if path_list[n] == hund_list(list_init):
print(change_list(list_init))
print(change_list(re_back(n)))
return
else:
print_list(path_list[n])
print(change_list(re_back(n)))
def heu_eight(): #啓發式搜索入口
while len(open_list) != 0:
list_temp = open_list.pop(0)
fa_path = hund_list(list_temp) # 作爲父狀態
if hund_list(list_temp) == hund_list(list_goal):
print_list(fa_path)
print("一共移動了" + str(scope) + "步")
return
#子狀態擴展
if list_temp[0] == 0:
n1 = list_temp[3] #下
list0_down = list_temp[:]
list0_down[3] = 0
list0_down[0] = n1
is_join(list0_down,fa_path,list_temp)
#path_list[hund_list(list0_down)] = fa_path #保存父子關係
n2 = list_temp[1] #右
list0_right = list_temp[:]
list0_right[1] = 0
list0_right[0] = n2
is_join(list0_right, fa_path, list_temp)
#path_list[hund_list(list0_right)] = fa_path # 保存父子關係
elif list_temp[1] == 0:
n1 = list_temp[0] #左
list1_left = list_temp[:]
list1_left[1] = n1
list1_left[0] = 0
is_join(list1_left, fa_path, list_temp)
#path_list[hund_list(list1_left)] = fa_path # 保存父子關係
n2 = list_temp[2] #右
list1_right = list_temp[:]
list1_right[1] = n2
list1_right[2] = 0
is_join(list1_right, fa_path, list_temp)
#path_list[hund_list(list1_right)] = fa_path # 保存父子關係
n3 = list_temp[4] #下
list1_down = list_temp[:]
list1_down[1] = n3
list1_down[4] = 0
is_join(list1_down, fa_path, list_temp)
#path_list[hund_list(list1_down)] = fa_path # 保存父子關係
elif list_temp[2] == 0:
n1 = list_temp[1] #左
list2_left = list_temp[:]
list2_left[2] = n1
list2_left[1] = 0
is_join(list2_left, fa_path, list_temp)
#path_list[hund_list(list2_left)] = fa_path # 保存父子關係
n2 = list_temp[5] #下
list2_down = list_temp[:]
list2_down[2] = n2
list2_down[5] = 0
is_join(list2_down, fa_path, list_temp)
#path_list[hund_list(list2_down)] = fa_path # 保存父子關係
elif list_temp[3] == 0:
n1 = list_temp[0] #上
list3_up = list_temp[:]
list3_up[3] = n1
list3_up[0] = 0
is_join(list3_up, fa_path, list_temp)
#path_list[hund_list(list3_up)] = fa_path # 保存父子關係
n2 = list_temp[4] #右
list3_right = list_temp[:]
list3_right[3] = n2
list3_right[4] = 0
is_join(list3_right, fa_path, list_temp)
#path_list[hund_list(list3_right)] = fa_path # 保存父子關係
n3 = list_temp[6] #下
list3_down = list_temp[:]
list3_down[3] = n3
list3_down[6] = 0
is_join(list3_down, fa_path, list_temp)
#path_list[hund_list(list3_down)] = fa_path # 保存父子關係
elif list_temp[4] == 0:
n1 = list_temp[1] #上
list4_up = list_temp[:]
list4_up[4] = n1
list4_up[1] = 0
is_join(list4_up, fa_path, list_temp)
#path_list[hund_list(list4_up)] = fa_path # 保存父子關係
n2 = list_temp[3] #左
list4_left = list_temp[:]
list4_left[4] = n2
list4_left[3] = 0
is_join(list4_left, fa_path, list_temp)
#path_list[hund_list(list4_left)] = fa_path # 保存父子關係
n3 = list_temp[5] #右
list4_right = list_temp[:]
list4_right[4] = n3
list4_right[5] = 0
is_join(list4_right, fa_path, list_temp)
#path_list[hund_list(list4_right)] = fa_path # 保存父子關係
n4 = list_temp[7] #下
list4_down = list_temp[:]
list4_down[4] = n4
list4_down[7] = 0
is_join(list4_down, fa_path, list_temp)
#path_list[hund_list(list4_down)] = fa_path # 保存父子關係
elif list_temp[5] == 0:
n1 = list_temp[2] #上
list5_up = list_temp[:]
list5_up[5] = n1
list5_up[2] = 0
is_join(list5_up, fa_path, list_temp)
#path_list[hund_list(list5_up)] = fa_path # 保存父子關係
n2 = list_temp[4] #左
list5_left = list_temp[:]
list5_left[5] = n2
list5_left[4] = 0
is_join(list5_left, fa_path, list_temp)
#path_list[hund_list(list5_left)] = fa_path # 保存父子關係
n3 = list_temp[8] #下
list5_down = list_temp[:]
list5_down[5] = n3
list5_down[8] = 0
is_join(list5_down, fa_path, list_temp)
#path_list[hund_list(list5_down)] = fa_path # 保存父子關係
elif list_temp[6] == 0:
n1 = list_temp[3] #上
list6_up = list_temp[:]
list6_up[6] = n1
list6_up[3] = 0
is_join(list6_up, fa_path, list_temp)
#path_list[hund_list(list6_up)] = fa_path # 保存父子關係
n2 = list_temp[7] #右
list6_right = list_temp[:]
list6_right[6] = n2
list6_right[7] = 0
is_join(list6_right, fa_path, list_temp)
#path_list[hund_list(list6_right)] = fa_path # 保存父子關係
elif list_temp[7] == 0:
n1 = list_temp[4] #上
list7_up = list_temp[:]
list7_up[7] = n1
list7_up[4] = 0
is_join(list7_up, fa_path, list_temp)
#path_list[hund_list(list7_up)] = fa_path # 保存父子關係
n2 = list_temp[6] #左
list7_left = list_temp[:]
list7_left[7] = n2
list7_left[6] = 0
is_join(list7_left, fa_path, list_temp)
#path_list[hund_list(list7_left)] = fa_path # 保存父子關係
n3 = list_temp[8] #右
list7_right = list_temp[:]
list7_right[7] = n3
list7_right[8] = 0
is_join(list7_right, fa_path, list_temp)
#path_list[hund_list(list7_right)] = fa_path # 保存父子關係
elif list_temp[8] == 0:
n1 = list_temp[5] #上
list8_up = list_temp[:]
list8_up[8] = n1
list8_up[5] = 0
is_join(list8_up, fa_path, list_temp)
#path_list[hund_list(list8_up)] = fa_path # 保存父子關係
n2 = list_temp[7] #左
list8_left = list_temp[:]
list8_left[8] = n2
list8_left[7] = 0
is_join(list8_left, fa_path, list_temp)
#path_list[hund_list(list8_left)] = fa_path # 保存父子關係
close_list.append(list_temp)
re_sort()
if __name__ == "__main__":
#輸入數據
x = input("請輸入初始狀態(用空格隔開):")
y = input("請輸入目標狀態(用空格隔開):")
# 數據處理
x_temp = x.strip().split(" ")
y_temp = y.strip().split(" ")
for i in range(len(x_temp)):
list_init.append(int(x_temp[i]))
for i in range(len(y_temp)):
list_goal.append(int(y_temp[i]))
path_list[hund_list(list_init)] = hund_list(list_init)
open_list.append(list_init)
# 判斷是否有解
if is_res():
print("移動路徑如下:")
heu_eight()
else:
print("無解")