8-Python中的Puzzle BFS输出问题

j2cgzkjk  于 2023-01-29  发布在  Python
关注(0)|答案(1)|浏览(127)

这是一个8的难题,使用bfs和dfs来解决,找到解决方案,并打印出路径的目标。我有麻烦弹出和附加的孩子,使它可以找到解决方案。我的错误是,它只会打印出两个选项,而不是从可能的解决方案分支。终端仍然在进行,尽管没有打印出任何东西。
这是我的代码,底部是一个测试用例。

import copy

#This is the only file you need to work on. You do NOT need to modify other files

# Below are the functions you need to implement. For the first project, you only need to finish implementing bfs() and dfs()

#here you need to implement the Breadth First Search Method
def bfs(puzzle):
    list = []
    #initialization 
    state = copy.deepcopy(puzzle)
    goal = [0,1,2,3,4,5,6,7,8]
    possible_move = [[1,3],[0,2,4],[1,5],[0,4,6],[1,3,5,7],[2,4,8],[3,7],[4,6,8],[5,7]]
    
     #appending the first state 
    queue = []
    queue = [Node(state)]
    
    for node in queue[:]:
      print('the state of this game position is:\n ' + str(node.state))
      loop = True
      notFound = True
      l = 0

    while loop:
        for node in queue:
            #blank index in each state 
            blank = node.state.index(8)
            print('the index of the blank is '+ str(blank))
            #The possible position 
            possible_pos = possible_move[blank]
            print('possible pos '+ str(possible_pos))
            if state != goal:
                for i in possible_pos:
                    possible_sw = copy.deepcopy(node.state)
                    print('index swap = '+ str(i))
                    
                    temp = possible_sw[i]
                    possible_sw[i] = 8
                    possible_sw[blank] = temp
                
                    print('the child nodes is ' + str(possible_sw))
                    node.insertChild(possible_sw)
                    
                    if possible_sw == goal:
                        print('end')
                        notFound = False
                        loop = False
                
    #check each child and find the goal state 
        for node in queue[:]:
            for child_state in node.children:
                if child_state == [0,1,2,3,4,5,6,7,8]:
                    final_state = child_state
                    print('the final state is '+ str(final_state.state))
            queue.pop(0)
            
        #find the parent path 
        while node.parent and loop is False:
            sol_path = final_state.state
            list.append(sol_path.index(8))
            if final_state.parent is not None:
                final_state = final_state.parent
            else: 
                parent = False
                list.reverse()
                list.pop(0)
                print('moves list '+ str(list))
    
    return list

#here you need to implement the Depth First Search Method
def dfs(puzzle):
    list = []
    return list

#This will be for next project
def astar(puzzle):
    list = []
    return list

def swap(list, pos1, pos2):
    list[pos1],list[pos2] = list[pos2], list[pos1]
    return list
        
class Node:
    def __init__(self,state,parent = None):
        self.parent = parent
        self.state = state
        self.children = []
        
    def insertChild(self, child_state):
        self.children.append(Node(child_state,self))

#test cases 

# p =[0, 1, 2, 3, 4, 5, 8, 6, 7]
p = [0, 1, 2, 3, 4, 5, 6, 8, 7]
#p = [0, 1, 2, 3, 8, 4, 6, 7, 5]
#p =[0, 4, 1, 3, 8, 2, 6, 7, 5]
bfs(p)
print("+++++++++++++++++++++")
#dfs(p)
cpjpxq1n

cpjpxq1n1#

您的尝试存在几个问题:

  • 队列不再接收更多的条目;queue.append不会被调用,另一方面,queue[:]上的内部循环清空了pop队列,删除了它唯一的元素,从那一刻起,队列保持为空。
  • Node构造函数只被调用一次,因此永远不会有多个节点,并且测试node.parent将始终为false,从而使最后一个while循环无效,并且永远不会打印moveslist(如果有
  • 如果在第一次迭代中没有找到终点--意味着初始位置离目标没有一步之遥--那么外部循环将进入无限循环:在其第二次迭代时,队列为空,因此不需要做任何事情,并且loop名称将永远不会变为True。
  • if state != goal没有什么意义,因为state名称在循环中从未改变。如果有任何改变,这应该引用node.state,而不是state
  • 最末尾的list.pop(0)不必要地删除了一个移动,循环条件已经检查了节点是否有父节点--所以跳过根状态--所以您将错过 * 两个 * 状态。
  • 代码不会检查 * 初始 * 位置是否可能是目标位置,因此在这种情况下,它不会返回一个空的移动列表作为解决方案。

其他一些备注:

  • swap永远不会被调用。
  • 该代码有几个没有任何用途的名称,如lnotFound
  • 它使用的是list,这是Python中的一个本地名称--选择一个不同的名称。
  • Node示例的children属性没有用,尽管你可以迭代它来找到最终状态,但是识别目标是否达到的逻辑已经存在于代码的其他地方......它不需要children
  • 不需要deepcopy:你使用的列表并不"深"。2你可以简单地通过应用list(本地)函数来复制它们,或者用[:]对它们进行切片。
  • 连续两次赋值给queue(在初始化中)会使第一次赋值无效,只需进行第二次赋值。
  • 初始化部分的循环不应该是一个循环。在那个时候你 * 知道 * 队列只有一个条目,所以迭代它是多余的。你可以使用puzzle输出初始状态。但是也许你想输出状态 * 在循环中 *...
  • temp不需要执行交换,首先,Python可以进行元组赋值,但也可以:移动并不是"真正"交换两个未知值:您知道其中一个是空单元格(8),因此可以安全地用另一个单元格的值覆盖该单元格,然后将另一个单元格的值设置为8--不需要temp

下面是使用上述注解更正的代码:

class Node:
    def __init__(self,state,parent = None):
        self.parent = parent
        self.state = state

def bfs(puzzle):
    solution = []
    #initialization 
    goal = [0,1,2,3,4,5,6,7,8]
    possible_move = [[1,3],[0,2,4],[1,5],[0,4,6],[1,3,5,7],[2,4,8],[3,7],[4,6,8],[5,7]]
    node = Node(puzzle)
    queue = [node]
    
    while True:
        node = queue.pop(0)
        print('the state of this game position is:\n ' + str(node.state))
        if node.state == goal:
            break
        blank = node.state.index(8)
        print('the index of the blank is '+ str(blank))
        possible_pos = possible_move[blank]
        print('possible pos '+ str(possible_pos))
        for i in possible_pos:
            possible_sw = node.state[:]
            print('index swap = '+ str(i))
            possible_sw[blank] = possible_sw[i]
            possible_sw[i] = 8
            print('the child node is ' + str(possible_sw))
            queue.append(Node(possible_sw, node))
        
    while node.parent:
        solution.append(node.state.index(8))
        node = node.parent

    solution.reverse()
    print('moves list '+ str(solution))
    return solution

相关问题