鱼C论坛

 找回密码
 立即注册
查看: 2633|回复: 2

[技术交流] python生成迷宫

[复制链接]
发表于 2020-6-3 19:08:47 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 java2python 于 2020-6-3 19:19 编辑

迷宫质量不论,总是迷宫吧。。。
  1. import random

  2. size_para = [15,25]
  3. size=[size_para[0]*2+3,size_para[1]*2+3]
  4. center=[size[0]//4*2+2,size[1]//4*2+2]
  5. map= [[100]*size[1] for i in range(size[0])]
  6. direct = ((-2,0),(2,0),(0,2),(0,-2))
  7. for y in range(size_para[0]):
  8.     for x in range(size_para[1]):
  9.         map[2*y+2][2*x+2] = 0

  10. step0_nodes = [center]
  11. map[center[0]][center[1]] = 10
  12. step1_nodes = []
  13. while len(step0_nodes) > 0:
  14.     node_no = random.randint(0,len(step0_nodes)-1)
  15.     yx= step0_nodes[node_no]
  16.     for d in range(0,4):
  17.         y=yx[0]+direct[d][0]
  18.         x=yx[1]+direct[d][1]
  19.         if(map[y][x] == 0):
  20.             step1_nodes.append((y,x))
  21.             map[yx[0]+direct[d][0]//2][yx[1]+direct[d][1]//2] = 10
  22.             map[y][x] = 10
  23.     step0_nodes.pop(node_no)
  24.     step0_nodes.extend(step1_nodes)
  25.     step1_nodes.clear()

  26. for y in range(1,size[0]-1):
  27.     str = ""
  28.     for x in range(1,size[1]-1):
  29.         if map[y][x] != 10:
  30.             str = str + "#"
  31.         else:
  32.             str = str + " "
  33.     print(str)
复制代码

随机的,结果:
  1. ###################################################
  2. # #     # # # # # #   #         # # # #         # #
  3. # ##### # # # # # ### ##### ##### # # # ### # ### #
  4. #             # # # #         #   # # # # # # # # #
  5. ############# # # # ####### ##### # # # # ##### # #
  6. #         #     #     # # # # # # #         # # # #
  7. ######### ##### ### ### # # # # # # ######### # # #
  8. #   # #   # # # # # #         #     # # #         #
  9. ### # ### # # # # # ####### ####### # # # #########
  10. #     #           # #   # # # # # # # #     #     #
  11. ##### ######### ### ### # # # # # # # # ##### #####
  12. # #   #   # # # # # #       #                     #
  13. # ### ### # # # # # ####### ### ### # # # ### # ###
  14. #     # # #       # # #   # # #   # # # # # # # # #
  15. ##### # # ### ### # # ### # # # ### ####### ##### #
  16. #           # #         # # #     #   # # #     # #
  17. ### # # ### ##### ##### # # # ######### # # ##### #
  18. #   # # #         # #             # # #   # # # # #
  19. # # ####### ### ### ### # # # ##### # ### # # # # #
  20. # # #       #   #       # # #     # #   #         #
  21. # ####### # ### ### # # # ### ##### # ### ### ### #
  22. # # #     # #   #   # # # #                 #   # #
  23. ### ### # # ####### ### ### # # # # # # # #########
  24. #       # # #       #   #   # # # # # # #       # #
  25. ##### # # ### # # ##### ### ### ####### ### # ### #
  26. #     # # #   # # #     #   #       #     # #     #
  27. ##### ##### # # ##### # ### ### ##### # ### # # # #
  28. #       #   # # # # # # #   #       # #   # # # # #
  29. ### # ########### # ####### # # # ##### ##### #####
  30. #   #   #                   # # # #         #     #
  31. ###################################################
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2020-6-5 20:17:15 | 显示全部楼层
所谓迷宫,结构上就是一棵树,没有环路,生成的方法,就是随机在图形中找一点,然后它有四个方向可以发展,这四个点加入step1_nodes,然后再把step1_nodes设回step0_nodes,再次产生候选节点,这样的话,发展节点就呈现以开始节点为中心以菱形向四周扩展的形态。那么就不是迷宫了,实际从起始点有四个候选点,他随机发展一个,以后的发展都是从step0_nodes中选取一个,发展出来的节点加入step0_nodes,当一个节点四周都是已经发展的节点了,那么这个节点就从step0_nodes删除,最后图形中找不到一个可以发展的点,所有step0_nodes的节点也被删除了,结构上就是一棵树,也就是迷宫(有所不同的是,迷宫的任何一个节点都可以作为根),设定一个起点,一个终点。

查找就简单了,就是从出发点发展,这次不是造迷宫,可以用菱形扩散法,也就是广度优先。

图形演示,图一是图中查找过程,图二是查找出的结果线路
和八皇后一样框架,这个程序的话,其中下面两句尤为重要,因为真的是画了很多线,虽然都很短,画完后,保存到图像,以后直接作为背景使用:

            select_rect = CMG.screen.subsurface(0,0,800,570)
            CMG.back_ground = select_rect.copy()
maze3.jpg
  1. import pygame
  2. import sys
  3. import os
  4. import random
  5. import time
  6. from pygame.locals import *
  7. import tkinter as tk
  8. from tkinter import *
  9. import tkinter.messagebox  # 要使用messagebox先要导入模块

  10. class Maze:
  11.     size = None
  12.     print_str=(('##','  '),('#',' '))
  13.     map = None
  14.     direct = ((-2,0),(2,0),(0,2),(0,-2),(-2,0),(2,0),(0,2))

  15.     @staticmethod
  16.     def check_move(map,yx):
  17.         for d in range(0,4):
  18.             if(map[yx[0]+Maze.direct[d][0]][yx[1]+Maze.direct[d][1]] == 0):
  19.                 return True
  20.         return False
  21.     @staticmethod
  22.     def create_maze(size_para):
  23.         WAY = 1
  24.         size=[size_para[0]*2+3,size_para[1]*2+3]
  25.         Maze.size = size
  26.         direct = Maze.direct
  27.         center=[random.randint(1,size[0]-1)//2*2,random.randint(1,size[1]-1)//2*2]
  28.         map= [[100]*size[1] for i in range(size[0])]
  29.         for y in range(size_para[0]):
  30.             for x in range(size_para[1]):
  31.                 map[2*y+2][2*x+2] = 0
  32.         step0_nodes = [center]
  33.         map[center[0]][center[1]] = WAY
  34.         step1_nodes = []

  35.         while len(step0_nodes) > 0:
  36.             node_no = random.randint(0,len(step0_nodes)-1)
  37.             yx= step0_nodes[node_no]
  38.             if not Maze.check_move(map,yx):
  39.                 step0_nodes.pop(node_no)
  40.                 continue
  41.             direct_start = random.randint(0,3)
  42.             for d in range(direct_start,direct_start+4):
  43.                 y=yx[0]+direct[d][0]
  44.                 x=yx[1]+direct[d][1]
  45.                 if(map[y][x] == 0):
  46.                     step1_nodes.append((y,x))
  47.                     map[yx[0]+direct[d][0]//2][yx[1]+direct[d][1]//2] = WAY
  48.                     map[y][x] = WAY
  49.                     break
  50.             step0_nodes.extend(step1_nodes)
  51.             step1_nodes.clear()
  52.         Maze.map = map

  53.     @staticmethod
  54.     def solve_maze(startY,endYX):
  55.         WAY = 1
  56.         direct = Maze.direct
  57.         center=(startY*2+2,2,-1)
  58.         map = Maze.map
  59.         steps_nodes = []
  60.         step0_nodes = [center]
  61.         map[center[0]][center[1]] = 0
  62.         step1_nodes = []

  63.         while len(step0_nodes) > 0:
  64.             steps_nodes.append(step0_nodes)
  65.             for n in range(0,len(step0_nodes)):
  66.                 yx= step0_nodes[n]
  67.                 for d in range(0,4):
  68.                     y=yx[0]+direct[d][0]
  69.                     x=yx[1]+direct[d][1]
  70.                     y3=yx[0]+direct[d][0]//2
  71.                     x3=yx[1]+direct[d][1]//2
  72.                     if(map[y3][x3] != 100 and map[y][x] == WAY ):
  73.                         step1_nodes.append((y,x,n))
  74.                         map[yx[0]+direct[d][0]][yx[1]+direct[d][1]] = 0
  75.                         if y == endYX[0]*2 and x== endYX[1]*2:
  76.                             steps_nodes.append(step1_nodes)
  77.                             return steps_nodes
  78.             step0_nodes = step1_nodes[:]
  79.             step1_nodes.clear()
  80.         return None

  81. class CMG: #画面显示管理
  82.     screen = None
  83.     map = None
  84.     gameAnswer = None
  85.     WHITE = (255, 255, 255)
  86.     GREEN = (0, 255, 0)
  87.     RED = (255, 0, 0)
  88.     BLUE = (0, 0, 255)
  89.     blocksize = 0
  90.     step = 0
  91.     back_ground = None

  92.     def __init__(self,screen,map,gameAnswer):
  93.         if CMG.screen == None:
  94.             #print("#############OS.PATH=%s"% os.path.dirname(os.path.abspath(__file__)))
  95.             CMG.screen = screen
  96.             CMG.map = map
  97.             CMG.gameAnswer = gameAnswer
  98.             if 800//len(map[0]) > 570//len(map):
  99.                 CMG.blocksize = 570//len(map)
  100.             else:
  101.                 CMG.blocksize = 800//len(map[0])
  102.         #如果存在对象成员
  103.         self.init_game_info()

  104.     def init_game_info(self):
  105.         pass

  106.     def printAll(self):
  107.         if CMG.step > len(CMG.gameAnswer):
  108.             return
  109.         CMG.screen.fill((0, 0, 0))
  110.         size = Maze.size
  111.         if CMG.back_ground == None:
  112.             for y in range(1,size[0]-1):
  113.                 for x in range(1,size[1]-1):
  114.                     val = CMG.map[y][x]
  115.                     if y%2==1 and x%2==0 and val == 100:
  116.                         #start_pos = [(y*CMG.blocksize,x*CMG.blocksize)]
  117.                         end_pos = [((x-1)*CMG.blocksize,y*CMG.blocksize),((x+1)*CMG.blocksize,y*CMG.blocksize)]
  118.                         pygame.draw.lines(CMG.screen, CMG.GREEN,0 , end_pos, 2)
  119.                     elif y%2==0 and x%2==1 and val == 100:
  120.                         end_pos = [(x*CMG.blocksize,(y-1)*CMG.blocksize),(x*CMG.blocksize,(y+1)*CMG.blocksize)]
  121.                         pygame.draw.lines(CMG.screen, CMG.GREEN,0 , end_pos, 2)
  122.             select_rect = CMG.screen.subsurface(0,0,800,570)
  123.             CMG.back_ground = select_rect.copy()
  124.         else:
  125.             self.screen.blit(CMG.back_ground,(0,0))
  126.         if CMG.step == len(CMG.gameAnswer):
  127.             step = CMG.step - 1
  128.             step_node = CMG.gameAnswer[step]
  129.             yx = step_node[len(step_node)-1]
  130.             while(yx[2]!=-1):
  131.                 y = yx[0]
  132.                 x = yx[1]
  133.                 step -= 1
  134.                 step_node = CMG.gameAnswer[step]
  135.                 yx = step_node[yx[2]]
  136.                 pygame.draw.rect(CMG.screen, CMG.WHITE, (((x-1)*CMG.blocksize+2,(y-1)*CMG.blocksize+2), (CMG.blocksize*2-4, CMG.blocksize*2-4)), 0)
  137.         else:
  138.             step_node = CMG.gameAnswer[CMG.step]
  139.             for s in range(0,len(step_node)):
  140.                 yx = step_node[s]
  141.                 y = yx[0]
  142.                 x = yx[1]
  143.                 #pygame.draw.rect(background, (0, 255, 0), ((200, 5), (100, 100)), 3)
  144.                 pygame.draw.rect(CMG.screen, CMG.WHITE, (((x-1)*CMG.blocksize+2,(y-1)*CMG.blocksize+2), (CMG.blocksize*2-4, CMG.blocksize*2-4)), 0)

  145.         CMG.step += 1

  146.     def moveAll(self):
  147.         pass

  148. #------------------------------------------------
  149. #tkinter,pygame混合区 START
  150. #------------------------------------------------
  151. root = tk.Tk()
  152. root.resizable(0,0)

  153. embed = tk.Frame(root, width = 800, height = 570) #creates embed frame for pygame window
  154. embed.grid(columnspan = (800), rowspan = 730) # Adds grid
  155. embed.pack(side = TOP) #packs window to the left

  156. buttonwin = tk.Frame(root, width = 800, height = 150)
  157. buttonwin.pack(side = BOTTOM)

  158. os.environ['SDL_WINDOWID'] = str(embed.winfo_id())
  159. os.environ['SDL_VIDEODRIVER'] = 'windib'

  160. screen = pygame.display.set_mode((800,570))

  161. #pygame.init()
  162. pygame.display.init()
  163. pygame.mixer.init()
  164. #------------------------------------------------
  165. #tkinter,pygame混合区 END
  166. #------------------------------------------------

  167. #参数,因为函数内要使用之外的变量,需要globe,因此全部打包
  168. class PARAM:
  169.     STATUS = 0
  170.     TICK_NORMAL = 5

  171. #按钮动作区 =====================================
  172. def exit_game():
  173.     global param
  174.     param.STATUS = 100
  175. #控件定义区 =====================================
  176. button_exit_b = Button(buttonwin,text = '退出画面', width=7, command=exit_game)
  177. button_exit_b.place(x=740,y=100)


  178. #状态,参数,循环中使用,比如STATUS=0:初次进入,1:...100:退出
  179. param = PARAM()
  180. Maze.create_maze([50,70])
  181. steps_nodes = Maze.solve_maze(0,(49,69))
  182. param.cmg = CMG(screen,Maze.map,steps_nodes)
  183. #------------------------------------------------
  184. #主函数,使用pygame框架,无限LOOP对各种事件然后相应处理
  185. #------------------------------------------------
  186. def main():
  187.     global param
  188.     #pygame.mixer.music.play(-1)
  189.     clock = pygame.time.Clock()

  190.     while True:
  191.         #这段event代码是必须的,哪怕在这个程序中不需要,不执行的话整个框架转不动
  192.         for event in pygame.event.get():
  193.             if event.type == QUIT:
  194.                 sys.exit()

  195.         #画面按钮按下后,修改param.STATUS,实际动作这里实现
  196.         if  param.STATUS == 100:
  197.             #退出按钮
  198.             if tk.messagebox.askokcancel('提示', '要退出画面吗'):
  199.                 break
  200.             param.STATUS = 0
  201.         elif param.STATUS == 10:
  202.             pass
  203.             
  204.         param.cmg.printAll()

  205.         #显示游戏画面
  206.         pygame.display.flip()
  207.         #设置帧率:长期画面不操作,设置成最闲
  208.         clock.tick(param.TICK_NORMAL)
  209.             
  210.         root.update()

  211. main()
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-5-8 18:47:48 | 显示全部楼层
大佬,我的论文可以引用你的代码吗,你是否有什么名字我可以把你加上去
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-4-19 22:48

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表