[pygame解题]DFS深度优先回溯算法

 

结果:

 

 

 

运行中截图:

 

 

题目规则:

 从红点出发,一笔连完所有格子,不能交叉,只能上下左右,不能斜向走。由此可以得出当路线长度等于粉色格子的个数时,题目有解。

状态树:

分析问题可以知道,此问题可以简化为一个子集树问题,在每一个点上都有上下左右几个方向可以生成几个叉枝,如下图。

 

 

 

 

回溯法:

 回溯法中,首先需要明确下面三个概念:
(一)约束函数:约束函数是根据题意定出的。通过描述合法解的一般特征用于去除不合法的解,从而避免继续搜索出这个不合法解的剩余部分。因此,约束函数是对于任何状态空间树上的节点都有效、等价的。
(二)状态空间树:刚刚已经提到,状态空间树是一个对所有解的图形描述。树上的每个子节点的解都只有一个部分与父节点不同。
(三)扩展节点、活结点、死结点:所谓扩展节点,就是当前正在求出它的子节点的节点,在DFS中,只允许有一个扩展节点。活结点就是通过与约束函数的对照,节点本身和其父节点均满足约束函数要求的节点;死结点反之。由此很容易知道死结点是不必求出其子节点的(没有意义)。

 

python代码实现:

 

import os ,time,pygame,sys

board = [[0, 1, 0, 1, 1, 1], 
         [1, 1, 1, 1, 1, 1], 
         [1, 1, 1, 1, 1, 1], 
         [0, 1, 1, 1, 0, 1], 
         [1, 1, 1, 1, 1, 1], 
         [1, 9, 1, 1, 1, 1]]
#地图矩阵
def findHea(board):
    '''
    找到头部
    '''
    for x in range(len(board)):
        for y in range(len(board[x])):
            if(board[x][y]==9):
                return [x,y]

def findC(board):
    '''
    找到障碍
    '''
    li=[]
    for x in range(len(board)):
        for y in range(len(board[x])):
            if(board[x][y]==0):
                li.append([x,y])
    return li


def jie(map):
    '''
    解出结果的条件
    '''
    jie = 0
    for x in range(len(board)):
        for y in range(len(board[x])):
            if(board[x][y]==1):
                jie+=1
    return jie

def isok(x,y):
    '''
    判断合法性(约束函数)
    '''
    try:
        if ((board[x][y]==0) or (x<0) or (x>len(board)) or (y<0) or (y>len(board[0]))):
            return False
        else:
            return True
    except :
        return False

C=findC(board)
def showMap(li):
    '''
    显示地图
    '''
    
    # board_C=board[:]
    board_C=[ [ "1" for o in range(6)] for i in range(6)]
    
    for n in li:
        board_C[n[0]][n[1]]=""

    for n in C:
        board_C[n[0]][n[1]]=""


    board_C[li[-1][0]][li[-1][1]]=""

    print(""+""*11+"")
    for c in board_C:
        c=[ " " if i=="1"  else i for i in map(str,c)]
        print(""+(" ".join(c))+"")
    print(""+""*11+"")


# showMap(luj)
def luy(x,y):

    '''
    查找分支,生成子树
    '''
    luy=[]
    for u in [[-1,0],[1,0],[0,-1],[0,1]]:#上下左右
        if isok(x+u[0],y+u[1]):
            # print(666)
            luy.append(u)
    return luy

def show_map(map):
    map=map[:]
    b=100
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
    for x in range(len(map)):
        for y in range(len(map[x])):
            if(map[x][y]==1):
                rec_x=y*(b+1)
                rec_y=x*(b+1)
                # print(rec_x,rec_y)
                pygame.draw.rect(wind, (255,155,155), (rec_x,rec_y,b,b), 0)
            if(map[x][y]==9):
                rec_x=y*(b+1)
                rec_y=x*(b+1)
                # print(rec_x,rec_y)
                pygame.draw.rect(wind, (255,0,0), (rec_x,rec_y,b,b), 0)
            if(map[x][y]==0):
                rec_x=y*(b+1)
                rec_y=x*(b+1)
                # print(rec_x,rec_y)
                pygame.draw.rect(wind, (255,255,255), (rec_x,rec_y,b,b), 0)

pygame.init()
wind=pygame.display.set_mode([600,600])
pygame.display.set_caption("迷宫求解")
background = pygame.Surface(wind.get_size())
background.fill((255, 255, 255))

def dfs(x,y,luj):
    '''
    回溯法
    '''
    lu=luy(x,y)
    for u in lu:#寻找分支
        if(isok(x+u[0],y+u[1]) and [x+u[0],y+u[1]] not in luj):
            luj_o=luj[:]
            luj.append([x+u[0],y+u[1]])
            # os.system("cls")

            
            wind.blit(background,(0,0))#pygame 绘制背景
            show_map(board)#绘制地图
            pygame.draw.lines(wind, (0,0,255), 0, [[i[1]*100+50,i[0]*100+50] for i in luj], 5)#绘制解法
            pygame.display.update()#刷新屏幕
            # time.sleep(0.5)


            # showMap(luj)
            if(len(luj)==jie):
                return luj
            ret=dfs(x+u[0],y+u[1],luj)
            if (type(ret)== type([])):
                return ret
            luj=luj_o[:]


jie=jie(board)+1
# print(jie)
luj=[findHea(board)]#初始化放入起点
#路径点列表
dfs_ok=dfs(findHea(board)[0],findHea(board)[1],luj)
print(dfs_ok)
while True:
    wind.blit(background,(0,0))#pygame 绘制背景
    show_map(board)#绘制地图
    pygame.draw.lines(wind, (0,0,255), 0, [[i[1]*100+50,i[0]*100+50] for i in dfs_ok], 5)#绘制解法
    pygame.display.update()#刷新屏幕
        
    
pygame.quit()

 

posted @ 2020-08-27 09:28  sunny开始学坏  阅读(422)  评论(0编辑  收藏  举报