使用啓發式搜索算法解決八數碼問題

描述過幾天再寫,先放代碼

#!/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("無解")


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章