[python 那些事儿] 八数码问题(更新中)

理论

问题描述:八数码问题是在一个3×3的方格盘上,放有1~8八个数码,余下一格为空格。空格可以与其四周的数码交换位置,从而改变八个数码在方格盘上的摆法。问题中可以使用的操作算子有四种:空格上移(up)、空格下移(down)、空格左移(left)、空格右移(right)

实验要求: 给定如下初始状态S0和目标状态Sg,要求编程实现:当输入初始状态S0后,通过搜索得到目标状态Sg,并记录下从S0到Sg的所有中间状态以及每一次状态改变所使用的操作算子。
在这里插入图片描述

(1)宽度优先搜索算法(伪代码):

Procedure_breadth_first_search:
Begin
    open:=[Initial state];  closed:=[Initial state];   //初始化     
    while open ≠ [ ] do
       begin
从open表中删除第一个状态,记作n;
           将n放入closed表中;
           if  n = 目标状态, then  return(success);       //成功,返回求解路径 
           生产n的所有子状态; 
           从n的子状态中删除已在open或closed表中出现的状态;//避免重复搜索
           将n的其余子状态,按生成的次序加入open表中已有结点的后面;
       end
end

(2)深度优先算法(伪代码):

Procedure_breadth_first_search:
Begin
    open:=[Initial state];  closed:=[Initial state]; d:=深度限制值;  //初始化     
    while open ≠ [ ] do
       begin
从open表中删除第一个状态,记作n;
           将n放入closed表中;
           if  n = 目标状态, then  return(success);       //成功,返回求解路径 
           if  n的深度<d,  then  continue;      //继续向深度方向搜索
生产n的所有子状态; 
           从n的子状态中删除已在open或closed表中出现的状态;//避免重复搜索
           将n的其余子状态,按生成的次序加入open表中已有结点的前面;
       end
end

代码

宽度优先搜索算法 (python代码)

import numpy as np
import copy

class test:
    def __init__(self,initial,goals):
    	self.length = int(math.sqrt(len(initial)))
        self.initial=np.reshape(initial,(self.length,self.length))
        self.goals=np.reshape(goals,(self.length,self.length))
        ##初始化程序
        self.open_=[self.initial]
        self.close_=[]
        
    #展示数据函数
    def __show_data(self,a):
        for i in a:
            print(i)
            
    #移动函数
    def __move(self,n,postion,row,col):
        if postion =="left":
            n[row,col] , n[row,col-1] = n[row,col-1], n[row,col]
        elif postion == "right":
            n[row,col] , n[row,col+1] = n[row,col+1], n[row,col]
        elif postion == "up":
            n[row,col] , n[row-1,col] = n[row-1,col], n[row,col]
        elif postion == "down":
            n[row,col] , n[row+1,col] = n[row+1,col], n[row,col]
        return n
    
    def __ifexists(self,three_result,close,open_):
        for i in range(len(close)):
            if (three_result == close[i]).all():
                #print("在close表中有重复")
                return True
        for i in range(len(open_)):
            if (three_result == open_[i]).all():
                #print("在open表中有重复")
                return True
        return False
    
    def find_do(self):
        flag = 0
        #print(self.open_)
        while self.open_:
            flag = flag+1
            #初始化算子
            direction=['up', 'down', 'right', 'left']
            #从open表中删除第一个状态并放入close表中
            n = self.open_.pop(0)
            self.close_.append(n)
            #print(n)
            #print(self.initial)

            #print(n==b)
            #如果n为目标状态则返回求解路径
            '''
            np.all所有都是true才能是true
            np.any一个是true就是true 
            '''
            #print(n)
            #print(self.goals)

            if (n == self.goals).all():
                print("展示搜索到的目标值")
                self.__show_data(n)
                print("----------------------------------找到目标值啦-----------------------------------")
                break 

            #生产n的所有子状态,并加入到open表后方
            postion = np.where(n == 0)
            #print(postion)
            #print("aa")

            i = postion[0]
            j = postion[1]
            length_down=n.shape[0]
            length_right=n.shape[1]



            #清除左操作
            if i==0:
                direction.remove("up")
            #清除上操作
            if j==0:
                direction.remove("left")
            #清除下操作
            if i == length_down-1:
                direction.remove("down")
            #清除右操作
            if j == length_right-1:
                direction.remove("right")
            #print(direction)
            
            #找到子状态
            for p in range(len(direction)):
                copy_n = copy.deepcopy(n)
                three_result = self.__move(copy_n,direction[p],i,j)
                #print(three_result)
                #判断是否存在于closeif (self.__ifexists(three_result,self.close_,self.open_)):
                    #直接跳出此次循环  不加入open表
                    continue
                self.open_.append(three_result)
                
            print("完成第"+str(flag)+"次查找,此轮中间项为:\n",n)



##初始化状态
a=[0,1,3,4,2,5,7,8,6]
b=[4,1,3,7,0,5,8,2,6]
#初始化类
test1 = test(a,b)
test1.find_do()

深度优先算法(python代码)

import numpy as np
import copy

class Node:
    def __init__(self,data,level):
        self.data=data
        self.level=level

class test1:
    def __init__(self,initial,goals):
        self.initial=Node(np.reshape(initial,(3,3)),0)
        self.goals=Node(np.reshape(goals,(3,3)),0)
        ##初始化程序
        self.open_=[self.initial]
        self.close_=[]
        self.b=15
        
    #展示数据函数
    def __show_data(self,a):
        for i in a.data:
            print(i)
            
    #移动函数
    def __move(self,n,postion,row,col):
        if postion =="left":
            n[row,col] , n[row,col-1] = n[row,col-1], n[row,col]
        elif postion == "right":
            n[row,col] , n[row,col+1] = n[row,col+1], n[row,col]
        elif postion == "up":
            n[row,col] , n[row-1,col] = n[row-1,col], n[row,col]
        elif postion == "down":
            n[row,col] , n[row+1,col] = n[row+1,col], n[row,col]
        return n
    
    def __ifexists(self,three_result,close,open_):
        for i in range(len(close)):
            if (three_result == close[i].data).all():
                #print("在close表中有重复")
                return True
        for i in range(len(open_)):
            if (three_result == open_[i].data).all():
                #print("在open表中有重复")
                return True
        return False
    
    def find_do(self):
        #遍历个数
        flag = 0
        #level
        level=1
        while self.open_:
            flag = flag+1
            #初始化算子
            direction=['up', 'down', 'right', 'left']
            #从open表中删除第一个状态并放入close表中
            n = self.open_.pop(0)
            self.close_.append(n)
            #print(n)
            #print(self.initial)

            #print(n==b)
            #如果n为目标状态则返回求解路径
            '''
            np.all所有都是true才能是true
            np.any一个是true就是true 
            '''
            #print(n.data)
            #print(self.goals)

            if (n.data == self.goals.data).all():
                print("展示搜索到的目标值")
                self.__show_data(n)
                print("----------------------------------找到目标值啦-----------------------------------")
                break 

            #生产n的所有子状态,并加入到open表后方
            postion = np.where(n.data == 0)

            i = postion[0]
            j = postion[1]
            length_down=n.data.shape[0]
            length_right=n.data.shape[1]



            #清除左操作
            if i==0:
                direction.remove("up")
            #清除上操作
            if j==0:
                direction.remove("left")
            #清除下操作
            if i == length_down-1:
                direction.remove("down")
            #清除右操作
            if j == length_right-1:
                direction.remove("right")
            
            
            if n.level>=self.b:
                continue
            #print(direction)
#             level = level+1
            #找到子状态
            for p in range(len(direction)):
                copy_n = copy.deepcopy(n)
                three_result = self.__move(copy_n.data,direction[p],i,j)
                #print(three_result)
                #判断是否存在于closeif (self.__ifexists(three_result,self.close_,self.open_)):
                    #直接跳出此次循环  不加入open表
                    continue
                    
                self.open_.insert(0,Node(three_result,n.level+1))

                
            print("完成第"+str(flag)+"次查找,此轮中间项为:\n",n.data)
            print("层数",n.level)
            #print("open表第一个数的内容",self.open_[0].data)
            
#             print("open表第一个数的内容",self.open_[0].data)
#             print("open表第一个数的level",self.open_[0].level)

#             print("open表第二个数的内容",self.open_[1].data)
#             print("open表第一个数的level",self.open_[0].level)


#             if flag==3:
#                 break


##初始化状态
a=[0,1,3,4,2,5,7,8,6]
b=[4,1,3,7,0,5,8,2,6]
#初始化类
test1 = test1(a,b)
test1.find_do()

猜你喜欢

转载自blog.csdn.net/qq_44172732/article/details/109141447