最近课内在学习《人工智能引论》、《数据结构》。
前者讲了Open/closed表、宽度、深度优先搜索策略,后者讲到了队列,两门课都期望解决给定初始状态和目标状态的九宫格问题。
用python,以队列驱动搜索,写了代码。
整体思路如下:
展示部分
用matplotlib绘制带有层级的点,代表搜索过程的状态,为这些点打上矩阵标签,就能得到良好的展示效果了。
(未带有标签)
(带有标签)
(如图,九宫格用0代表空位,初始状态为:[[2,8,3],[1,6,4],[7,0,5]],目标状态为[[1,2,3],[8,0,4],[7,6,5]])
(目标状态是一个顺时针的1-8)
要达到这样的展示效果,需要为matplotlib提供节点位置(x:由本层节点的个数及当前点在本层的位置决定,y:由节点的层次决定。),及对应该节点的矩阵标签。
数据的设计:
open表/closed表存储了这样的一些节点:每个节点存储两个信息:矩阵、节点层级。
矩阵会发生改变,而节点层级又不唯一,字典要求键不改变且唯一,因此不能采用字典存储。
选择使用二元组存储。即(矩阵,层级)。
此处矩阵是二维列表。
进行主循环时,从open表头部取出节点,如果不在closed表中,则将其可能的后续节点加入open表,加入到头部是深度优先搜索,加入到尾部是宽度优先搜索。
这样,在同层级,不会出现重复的节点,但在不同层级,又允许矩阵相同的节点存在。
代码如下,笔者是新手,如果有误,还望见谅。
宽度优先搜索代码:
#人工智能引论作业:宽度优先搜索探索九宫格走法
#在最后一层的最后一个节点,达到了目标状态
#python==3.7.3
#matplotlib==3.1.0
#numpy==1.16.4
import matplotlib.pyplot as plt
import numpy as np
from copy import deepcopy as dp
#用于matplotlib正常显示中文标签
plt.rcParams['font.sans-serif']=['SimHei']
#矩阵标签的像素大小。
lableSize=8
#获取0的位置,即空的位置
def getZeroPosition(twoArray):
for i in range(len(twoArray)):
for k in range(len(twoArray[i])):
if twoArray[i][k]==0:
return i,k
#进行0(空位置)与其他位置的交换:操作符/算子定义
def zeroUp(myArray):
zero_x,zero_y=getZeroPosition(myArray)
t=myArray[zero_x-1][zero_y]
myArray[zero_x-1][zero_y]=0
myArray[zero_x][zero_y]=t
def zeroDown(myArray):
zero_x,zero_y=getZeroPosition(myArray)
#print(zero_x,zero_y)
t=myArray[zero_x+1][zero_y]
myArray[zero_x+1][zero_y]=0
myArray[zero_x][zero_y]=t
def zeroRight(myArray):
zero_x,zero_y=getZeroPosition(myArray)
t=myArray[zero_x][zero_y+1]
myArray[zero_x][zero_y+1]=0
myArray[zero_x][zero_y]=t
def zeroLeft(myArray):
zero_x,zero_y=getZeroPosition(myArray)
t=myArray[zero_x][zero_y-1]
myArray[zero_x][zero_y-1]=0
myArray[zero_x][zero_y]=t
#初始状态
beginData=[[2,8,3],[1,6,4],[7,0,5]]
#目标状态
endData=[