八数码难题——盲目搜索(不显示移动步骤)

文章介绍了使用Python编程解决八数码难题的盲目搜索算法。通过定义字串表示九宫格状态,利用双向列表存储搜索路径,遵循深度优先或宽度优先策略进行搜索,最终找到从初始布局到目标布局的解决方案。文章提供了一个不显示移动步骤的简化版本代码示例。
摘要由CSDN通过智能技术生成

八数码难题是一个典型的搜索问题,出现在各种教材中,用来演示盲目搜索,启发式搜索的实现过程。这里给出的程序遵循标准的盲目搜索、启发式搜索算法编写,供初学基础搜索的同学比对参考。这里先给出只显示问题可解,不显示移动步骤的代码,可以直接简明地显示盲目搜索的步骤。

from collections import deque # 导入双向列表对象

'''把九宫格描述成字串,空格用0表示,移动九宫格就是交换字串字符,0与其它位置的字符交换'''

# 声明全局变量
closed = []
open = deque([]) 

# 交换规则,不能随意交换字符。对字串'123405678',0在位置4,即在九宫格中间,可以和九宫格的四个相邻位置交换,就是和字串的四个位置1,3,5,7。以字典形式给出交换规则,key是0的位置,value是可允许的交换位置。 
dic_of_rule = {0:[1, 3], 1:[0, 2, 4], 2:[1, 5],
                 3:[0,4,6], 4:[1,3,5,7], 5:[2,4,8],
                 6:[3,7],  7:[4,6,8], 8:[5,7]}
# 定义函数

def swap_chr(str1, i, j): #交换字串str的i,j位置的字符,把字串转成list交换,然后变回字串
    str2list = list(str1)
    str2list[i], str2list[j] = str2list[j],str2list[i]
    a = ''.join(str2list) # 转回字串
    return a

# 盲目搜索的三个步骤:open弹节点n并放closed里面,与目标比较(成功退出),展开 n 的子节点放入open。
# 这里把展开一个节点做出一个函数,返回值是一个展出的串的列表。 
def expand(now): # 展开now
        expanded = []
        zero_pos = now.index("0")
        allowed_pos = dic_of_rule[zero_pos]#当前可进行交换的位置集合
        for k in allowed_pos:
            newstr = swap_chr(now,k, zero_pos) # 与可允许的交换位置执行交换,生成newstr。
            if newstr not in closed: # 检测newstr在不在closed中
                expanded.append(newstr)
        return expanded

# 主代码  
if __name__ == "__main__":
    startlayout = "541203786"
    endlayout = "123804765"
    open.append(startlayout)
    iter = 0 # 记录找了多少次的变量
    # 以上是为下面循环准备的初始化,进入循环前必须初始化。

    while 1:
        iter +=1
        if len(open) == 0:
            print('不能移动到目标。')
            break
        else:
            # now = open.popleft() # 从open 右弹出,队列,宽度优先搜索
            now = open.pop() # 从open 左弹出,栈,深度优先搜索
            closed.append(now) # 放入closed
            if now == endlayout: # 比较检查找没找到目标,如到达目标 
                print('共搜索{}步,能移动到目标'.format(iter))
                break
            else:
                expanded = expand(now) # 如没有找到,展开当前now 节点。
                open.extend(expanded) # 把展开节点加到open中,这里用extend方法实现
                # 此处记住,open=open.extend(expanded)会出现错误,因为extend()方法是in-place的,没有返回值。

运行结果:

共搜索14104步,能移动到目标

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值