八数码问题 python实现 A*启发式搜索

class board(object):
    def __init__(self):
        # self.groud = [1,0,2,3,4,5,6,7,8]
        # 棋盘,0代表空
        self.groud = [7, 2, 4, 5, 0, 6, 8, 3, 1]
        #移动的路径
        self.route = []

    def __lt__(self,other):
        return self.priority()<other.priority()
    
# 是否到达正确状态
    def guiwei(self):
        flag = True
        for i in range(9):
            if self.groud[i] != i:
                flag = False
                break
        return flag
# 两个位置数字进行交换
    def exchange(self, index1, index2):
        temp = self.groud[index1]
        self.groud[index1] = self.groud[index2]
        self.groud[index2] = temp
# 空格向左移动
    def left(self):
        index = self.groud.index(0)
        if index % 3 != 0:
            self.exchange(index, index-1)
# 空格向右移动
    def right(self):
        index = self.groud.index(0)
        if index % 3 != 2:
            self.exchange(index, index+1)
# 空格向上移动
    def up(self):
        index = self.groud.index(0)
        if int(index/3) != 0:
            self.exchange(index, index-3)
# 空格向下移动
    def down(self):
        index = self.groud.index(0)
        if int(index/3) != 2:
            self.exchange(index, index+3)
# 返回空格能移动的方位的列表,比如[0,1,2,3]代表空格能向左右上下进行移动
    def can_move(self):
        index = self.groud.index(0)
        can = []
        if index % 3 != 0:
            can.append(0)
        if index % 3 != 2:
            can.append(1)
        if int(index/3) != 0:
            can.append(2)
        if int(index/3) != 2:
            can.append(3)
        return can
# 展示棋盘
    def show_board(self):
        print(self.groud)
# 路径
    def show_route(self):
        print(self.route)
        print(len(self.route))
# 通过route路径进行移动,route是路径列表
    def move(self, route):
        for i in route:
            if i == 0:
                self.left()
            elif i == 1:
                self.right()
            elif i == 2:
                self.up()
            else:
                self.down()
# 仅移动一步
    def move_one(self, i):
        if i == 0:
            self.left()
        elif i == 1:
            self.right()
        elif i == 2:
            self.up()
        else:
            self.down()
# 测试如果向目标方向移动,棋盘的变化,返回变化的棋盘
    def test(self, i):
        groud = []
        if i == 0:
            self.left()
            groud = self.groud[:]
            self.right()
        elif i == 1:
            self.right()
            groud = self.groud[:]
            self.left()
        elif i == 2:
            self.up()
            groud = self.groud[:]
            self.down()
        else:
            self.down()
            groud = self.groud[:]
            self.up()
        return groud

    def route_0(self,route):
        route_0 = []
        for x in route:
            self.move_one(x)
            route_0.append(self.groud.index(0))
        print(route_0)
    # 优先级计算
    def priority(self):
        p = 0
        for i in range(9):
            if self.groud[i] != i:
                p+=1
        # return p
        return p+len(self.route)
import queue
def A_star():
    # 值越小,优先级越高
    deq = queue.PriorityQueue()
    appear = set()#使用set进行检索极快,hash检索
    temp = board()
    appear.add(list2str(temp.groud))
    for x in temp.can_move():
        b = board()
        b.move_one(x)
        b.route.append(x)
        appear.add(list2str(b.groud))
        deq.put(b)
    flag = 0
    while True:
        flag+=1
        temp = deq.get()
        if flag%10000==0:
            flag=0
            temp.show_board() 
            temp.show_route()

        if  temp.guiwei():
            temp.show_board() 
            temp.show_route()
            break
        for x in temp.can_move():
            # 筛选掉重复的棋盘情况,加快搜索速度
            if list2str(temp.test(x)) not in appear:
                new_temp=copy.deepcopy(temp)
                new_temp.move_one(x)
                new_temp.route.append(x)
                deq.put(new_temp)
                appear.add(list2str(new_temp.groud))   

要点

  • 数据结构变为了优先队列.使用的是queue中的PriorityQueue
  • 优先级的计算使用的是多少个位置没复位,比如102345678有7个复位了,2个没复位.另外一个则是加上路径的长度.数字越小则优先级越高.
  • 在board类中使用priority方法实现__lt__()方法,让board可比.方便使用优先级队列

只用复位,即不追求最短
在这里插入图片描述
追求最短
八数码问题 python实现 A*启发式搜索_第1张图片

你可能感兴趣的:(人工智能)