基于A*算法的迷宫小游戏

文章目录

  • 前言
  • 一、程序设计说明
    • 1.功能描述
    • 2.算法思想
  • 二、模块设计
    • 1.流程设计
    • 2.算法实现
    • 3.界面设计
  • 三、功能演示


前言

本文采用A*算法的思想,借助pycharm下的python环境,求解迷宫的最优路径问题。


一、程序设计说明

1.功能描述

①根据用户界面的提示,可以自定义生成一个迷宫;

②本迷宫所采用的主要算法为启发式A*算法,通过其寻找到一条起点和终点间的最短距离,输出走迷宫的最优路径并显示。

2.算法思想

(1)A*算法介绍

A算法是一种启发式搜索算法。在A*算法中,从起点开始后,通过启发函数来检查相邻方格,找到代价最小的“节点”作为下一个“父节点”,不断地搜索直到找到最优解。

(2)open表和close表

A*算法的两个重要数据列表:

①open表:用来存储可能用来寻找最短路径的可到达或通过的方格

②close表:用来存储不再需要检查或无法通过的方格

(3)启发函数

启发函数是A*算法的核心,在选择路径的过程中发挥重要作用。其表达式如下:

  f(n)=g(n)+h(n)

g(n)表示的是从起点到当前位置所产生的实际移动代价;
h(n)表示的是从当前位置到终点的预估移动代价。

h(n)的选取保证了找到最短路径这一条件,计算h(n)的方法有许多种,本文主要采用的是曼哈顿方法,即计算从当前格到目的格之间水平和垂直的方格的数量总和。

此外,A算法的启发函数还要满足的条件是:h(n)≤h*(n) (h*(n)为实际距离的代价值)。

(4)算法流程

① 首先初始化open表和close表,将开始节点放入open表中,此时开始节点的g值和h值都为0。

② 将所有可到达的方格作为相邻节点加入open表中,通过启发函数计算这些节点的f值,找到值最小的节点。

③ 将open表中的父节点删除,放入close表中。

④ 将找到的f值最小的节点作为现在的父节点,不断地重复循环遍历,找到下一个当前节点和其相邻结点f值最小的节点作为父节点。
若相邻节点不可通过或者已经在close中,则不执行任何操作;
若相邻节点不在open表中,则将其加入open表中,当前节点为其父节点,计算出它们之间的f值;
若相邻节点已经在open表中,则判断此时的当前节点和该相邻节点间的f值是否更小,如果是,则更新此时的f值。

⑤ 当最终的目的节点被加入到open列表时,表明此时已经找到了最短路径;否则,直到open列表空时也没有找到目的节点,则表明找不到路径,结束遍历。

二、模块设计

1.流程设计

(1)游戏流程
基于A*算法的迷宫小游戏_第1张图片
(2)寻找最短路径流程
基于A*算法的迷宫小游戏_第2张图片

2.算法实现

重要代码:

(1)判断终点是否在open表中

    def endInOpenList(self):
        for i in self.openList:
            if self.endPoint[0] == i.x and self.endPoint[1] == i.y:
                return True
        return False

(2)将节点加进open表前需检查其是否已经在open表中

    def inOpenList(self, p1):
        for i in range(0, len(self.openList)):
            if p1.isEq(self.openList[i]):
                return i
        return -1

(3)A star算法寻路

    def AstarMap(self):
        self.openList.append(self.startPoint)  # 将起点放到open表中
        while (not self.isOK): # 先检查终点是否在open表中 ,有则结束
            if self.inOpenList(self.endPoint) != -1:  
                self.isOK = True  
                self.end = self.openList[self.inOpenList(self.endPoint)]
                self.route.append(self.end)
                self.te = self.end
                while (self.te.parentPoint != 0):
                    self.te = self.te.parentPoint
                    self.route.append(self.te)
            else:
                self.sortOpenList()  # 将估值最小的节点放在index = 0
                Minnode = self.openList[0]  # Minnode为估值最小节点
                self.openList.pop(0)
                self.closeList.append(Minnode)
                     

3.界面设计

(1)设计窗体布局,以及实现迷宫的画布

 self.root = Tk()
        self.root.title('A*算法实现迷宫')
        self.root.geometry("1050x600+200+50") #设置窗口大小
self.canvas = Canvas(self.root, width=500, height=500, bg="white")
        self.canvas.pack(side='left')
        for i in range(1, 10):
            self.canvas.create_line(50, 50 * i, 450, 50 * i)  # 横线
            self.canvas.create_line(50 * i, 50, 50 * i, 450)  # 竖线
        self.canvas.bind("", self.drawMapBlock)# 将画布绑定到迷宫区域
        self.root.mainloop()

(2)设计障碍物、起点、终点、所寻路径的颜色

self.blockcolor = ['black', 'green', 'red', 'purple']  # 设置障碍为黑色,起点为绿色 终点为红色,路径为紫色
        self.mapStatus = np.ones((8, 8), dtype=int)  # 地图状态数组(全0数组) 1无障碍 0障碍
#颜色设置
    def selectobstacle(self):
        self.blockcolorIndex = 0  #黑色
    def selectstart(self):
        if not self.selectedStart:
            self.blockcolorIndex = 1  # 绿色
        else:
            self.blockcolorIndex = 0  # 黑色
    def selectend(self):
        if not self.selectedEnd:
            self.blockcolorIndex = 2  # 红色
        else:
            self.blockcolorIndex = 0  # 黑色
    def selectaction(self):
        self.blockcolorIndex = 0  # 黑色
        self.AstarMap()
        self.route.pop(-1)
        self.route.pop(0)
        for i in self.route:
            self.canvas.create_rectangle((i.x + 1) * 50, (i.y + 1) * 50, (i.x + 2) * 50, (i.y + 2) * 50, fill='purple')

(3)设计五个功能,分别为选择障碍,选择起点,选择重点,开始寻路和重新开始。

self.btn_obstacle = Button(self.root, text="选择障碍", command=self.selectobstacle)
        self.btn_obstacle.pack(side='left',anchor='n')
        self.btn_start = Button(self.root, text="选择起点", command=self.selectstart)
        self.btn_start.pack(side='left',anchor='n')
        self.btn_end = Button(self.root, text="选择终点", command=self.selectend)
        self.btn_end.pack(side='left',anchor='n')
        self.btn_pathfinding = Button(self.root, text="开始寻路", command=self.selectaction)
        self.btn_pathfinding.pack(side='left',anchor='n')
        self.btn_restart = Button(self.root, text="重新游戏", command=self.selectrestart)
        self.btn_restart.pack(anchor='w')

三、功能演示

设置迷宫,寻路结果如下:
基于A*算法的迷宫小游戏_第3张图片

你可能感兴趣的:(基于A*算法的迷宫小游戏)