当前位置: 首页 > 后端技术 > Python

用Python做一个迷宫游戏

时间:2023-03-26 11:16:05 Python

相信大家都玩过迷宫游戏。对于简单的迷宫,我们一眼就能看到路径,但是对于复杂的迷宫,可能需要很长时间,甚至几天,然后可能要从入口和出口两边搜索才能找到路径,否则您甚至可能找不到路径。虽然迷宫问题对于我们人类来说比较复杂,但是对于计算机来说却是非常简单的问题。为什么这么说呢,因为看似复杂,其实是有规律可循的。我们可以提着一根很长的绳子,从入口处直走。如果路上有岔路口,就走最左边的岔路口,直到走到死胡同或找到出路。如果是死胡同,回到上一个岔路口,我们称之为岔路口A,然后进入左边第二个岔路口,进入第二个岔路口后重复第一个岔路口的步骤,直到找到出路或者回到死胡同。当你在岔路口走完所有的岔路口后,沿着找到出口前的绳索往回走,走到岔路口A的前一个路口B,重复以上步骤。不知道大家有没有发现,这其实就是一个递归的过程,而这正是计算机所擅长的。上面的走迷宫算法就是我们常说的深度优先遍历算法,相对于广度优先遍历算法。有了理论基础,下面我们来尝试用程序实现一个走迷宫的小程序。生成迷宫的算法有很多。常用的有递归回溯、递归划分和随机Prim算法。我们今天使用的最后一种算法。算法的主要步骤如下:1.迷宫的行和列必须是奇数。2、奇数行和奇数列的交点是一条路,其余的点是墙。迷宫四周是围墙。3.选择一个单元格作为道路(本例中选择[1,1]),然后将其相邻的墙放入列表wall4。当列表墙中有墙时:4.1.从列表中随机选择一面墙。如果墙隔开两个cell只访问过一个cell4.1.1,那么从列表中移除这堵墙,同时打开墙通过4.1.2,将cell标记为visited4.1.3,移除相邻的未访问单元格的墙添加到列表wall4.2。如果这堵墙两边的单元格都被访问过,那么就把这堵墙从列表中移除。我们定义一个Maze类,用一个二维数组表示迷宫图,其中1表示墙,0表示路,然后初始化左上角为入口,右下角为出口,最后定义向下方向矢量。迷宫类:def__init__(self,width,height):self.宽度=宽度自身。身高=自己的身高。map=[[0ifx%2==1andy%2==1else1forxinrange(width)]foryinrange(height)]self.map[1][0]=0#entryself.map[height-2][width-1]=0#exitself.visited=[]#rightupleftdownself.dx=[1,0,-1,0]self.dy=[0,-1,0,1]接下来是生成迷宫的主要函数。defgenerate(self):start=[1,1]self.visited.append(start)wall_list=self.get_neighbor_wall(start)而wall_list:wall_position=random.choice(wall_list)neighbor_road=self.get_neighbor_road(wall_position)wall_list。remove(wall_position)self.deal_with_not_visited(neighbor_road[0],wall_position,wall_list)self.deal_with_not_visited(neighbor_road[1],wall_position,wall_list)这个函数里面主要有两个函数:get_neighbor_road(point)和deal_with_not_visited()。传入坐标点point的相邻道路节点,返回值为二维数组,后面的deal_with_not_visited()函数处理步骤4.1的逻辑。由于Prim随机算法是随机选择列表中的所有单元格,新加入的单元格与旧加入的单元格被选中的概率相同,所以分支较多,生成的迷宫更复杂。它更难,但当然看起来更自然。生成的迷宫。[1,1,1,1,1,1,1,1,1,1,1][0,0,0,0,0,0,0,0,0,0,1][1,1,1,1,1,0,1,1,1,1,1][1,0,0,0,0,0,0,0,0,0,1][1,1,1,0,1,0,1,0,1,0,1][1,0,0,0,1,0,1,0,1,0,1][1,0,1,0,1,0,1,1,1,1,1][1,0,1,0,1,0,0,0,0,0,1][1,0,1,0,1,1,1,0,1,0,1][1,0,1,0,1,0,0,0,1,0,0][1,1,1,1,1,1,1,1,1,1,1]走出迷宫拿到迷宫的地图,然后按照我们文章开头的思路走迷宫即可。主要函数逻辑如下:defdfs(self,x,y,path,visited=[]):#outOfIndexifself.is_out_of_index(x,y):returnFalse#visitedoriswallif[x,y]invisitedorself.get_value([x,y])==1:returnFalsevisited.append([x,y])path.append([x,y])#end...ifx==self.width-2andy==self.height-2:returnTrue#recursiveforiinrange(4):if00:#drawrouteoffset=pixel/2foriinrange(len(self.route)-1):curr=self.route[i]next=self.route[i+1]self.color=backtrack_colorifcurrinself.route[:i]andnextinself.route[:i]否则route_colorpyxel.line(curr[0]+offset,(curr[1]+offset),next[0]+offset,next[1]+offset,self.color)pyxel.circ(self.route[-1][0]+2,self.route[-1][1]+2,1,head_color)defupdate(自我):如果pyxel.btn(pyxel.KEY_Q):pyxel.quit()如果pyxel.btn(pyxel.KEY_S):自我。death=Falseifnotself.death:self.check_death()self.update_route()defcheck_death(self):ifself.dfs_model和len(self.route)==len(self.dfs_route)-1:self.death=Trueelif不是self.dfs_model和len(self.route)==len(self.bfs_route)-1:self.death=Truedefupdate_route(self):index=int(self.index/self.step)self.index+=1ifindex==len(self.route):#移动ifself.dfs_model:self.route.append([pixel*self.dfs_route[index][0],pixel*self.dfs_route[index][1]])else:self.route.append([pixel*self.bfs_route[index][0],pixel*self.bfs_route[index][1]])App()至此,我们就完全从迷宫中生成了,到Findingthepath再到visualizethepath都已经实现了。直接调用主函数App()按S键开始游戏小结今天我们使用深度优先算法实现迷宫的遍历。对于新手来说,递归的思想可能比较难理解,但这是符合计算机思维的,随着经验的加深,理解会越来越深。其次,我们使用pyxel库来实现路径可视化。难点在于坐标的计算和更新。有很多细节和繁琐。当然,读者也可以使用其他库或者直接使用网页来实现。