生成2/3D迷宫

机械唯物主义 : linjunhalida <linjunhalida@gmail.com>
sender-time     Sent at 14:23 (GMT+08:00). Current time there: 4:43 PM. ✆
reply-to        python-cn@googlegroups.com
to      python-cn`CPyUG`华蟒用户组 <python-cn@googlegroups.com>
date    Fri, Apr 16, 2010 at 14:23

subject [CPyUG] 一个迷宫生成的python程序

动机

看到一篇文章,关于如何通过DFS来生成迷宫的介绍:

于是手痒写了代码,如附件,给大家玩玩。

非常好的想法,可以应用在其他更加复杂的迷宫生成上面。

test.png

mapmaze.py

Toggle line numbers
   1 #!/usr/bin/env python
   2 #-*- coding:utf-8 -*-
   3 """
   4 use map depth first search to create a maze.
   5 """
   6 import random
   7 import numpy as np
   8 
   9 DIRS = ((0, +1),
  10         (0, -1),
  11         (-1, 0),
  12         (+1, 0))
  13 
  14 def create_maze(mw, mh):
  15     """
  16     assume maze is a map,
  17     use depth first search to connect the map,
  18     and so is a maze.
  19     """
  20     path = [(0,0)] #the search path
  21     vector_link = [] #links between vectors, for draw maze
  22     visited = np.zeros((mw,mh)) #for O(1) search
  23     visited[0,0] = 1
  24 
  25     while True:
  26         #get next vector
  27         nextp = get_next(path, visited, mw, mh)
  28         #check if this vector is the end
  29         if not nextp:
  30             # if so, pop to previous head
  31             path.pop()
  32             # if path is empty, search is finished
  33             if path == []:
  34                 #finish search
  35                 break
  36             continue
  37         #store data, move to next head
  38         vector_link.append((path[-1],nextp))
  39         visited[nextp] = 1
  40         path.append(nextp)
  41 
  42     #create maze
  43     maze = np.ones((mw*2-1, mh*2-1), dtype=np.int)
  44     for start, end in vector_link:
  45         #print start, end
  46         d1 = start[0]*2, start[1]*2
  47         d2 = end[0]*2, end[1]*2
  48         middle = ((start[0] + end[0]),
  49                   (start[1] + end[1]))
  50         maze[d1] = 0
  51         maze[d2] = 0
  52         maze[middle] = 0
  53     return maze
  54 
  55 def get_next(path, visited, mw, mh):
  56     """
  57     get what is the next vector?
  58     """
  59     head = path[-1]
  60     nextps = [] #store next vectors
  61     for mod in DIRS:
  62         newp = head[0] + mod[0], head[1] + mod[1]
  63         #out of the scope
  64         if ((0 > newp[0]) or (mw <= newp[0]) or
  65             (0 > newp[1]) or (mh <= newp[1])
  66             ):
  67             continue
  68         #have visited
  69         if visited[newp] == 1:
  70             continue
  71         nextps.append(newp)
  72     if nextps == []:
  73         return None
  74     #random choose a vector
  75     return nextps[random.randint(0, len(nextps)-1)]
  76 
  77 def show_maze(maze):
  78     """
  79     print maze to command line.
  80     """
  81     for row in maze:
  82         print "".join(["%d"%i for i in row])
  83 
  84 def draw_maze(maze):
  85     """
  86     use pygame to render a png file.
  87     """
  88     try:
  89         import pygame
  90     except:
  91         print "looks like you don't have pygame,"
  92         print "install pygame for rending a image file."
  93     pygame.init()
  94 
  95     DOT = 8
  96     size = maze.shape
  97     sw, sh = size
  98 
  99     surface = pygame.Surface((sw*DOT, sh*DOT))
 100     for i in range(sw):
 101         for j in range(sh):
 102             if maze[i][j] == 0:
 103                 surface.fill((200,200,200), 
 104                              pygame.Rect(i*DOT, j*DOT, DOT, DOT))
 105     pygame.image.save(surface, "test.png")
 106 
 107 def main():
 108     maze = create_maze(20,20)
 109     show_maze(maze)
 110     draw_maze(maze)
 111 
 112 if __name__=="__main__":
 113     main()

multi_maze.py

Toggle line numbers
   1 #!/usr/bin/env python
   2 #-*- coding:utf-8 -*-
   3 """
   4 use map depth first search to create a maze.
   5 this map is multi dimension!
   6 """
   7 import random
   8 import numpy as np
   9 
  10 def create_maze(*size):
  11     """
  12     assume maze is a map,
  13     use depth first search to connect the map,
  14     and so is a maze.
  15     """
  16     dim = len(size) #dimension
  17     start = np.zeros(dim, dtype=np.int)
  18     path = [start] #the search path
  19     vector_link = [] #links between vectors, for draw maze
  20     visited = np.zeros(size, dtype=np.bool) #for O(1) search
  21     visited[tuple(start.tolist())] = True
  22     #directions
  23     DIRS = []
  24     for i in range(dim):
  25         z = np.zeros(dim, dtype=np.int)
  26         z[i] += 1
  27         DIRS.append(z)
  28         z = np.zeros(dim, dtype=np.int)
  29         z[i] -= 1
  30         DIRS.append(z)
  31 
  32     while True:
  33         #get next vector
  34         nextp = get_next(path, visited, size, DIRS)
  35         #check if this vector is the end
  36         if nextp is None:
  37             # if so, pop to previous head
  38             path.pop()
  39             # if path is empty, search is finished
  40             if path == []:
  41                 #finish search
  42                 break
  43             continue
  44         #store data, move to next head
  45         vector_link.append((path[-1],nextp))
  46         visited[tuple(nextp.tolist())] = 1
  47         path.append(nextp)
  48 
  49     #create maze
  50     maze_size = np.array(size)*2 -1
  51     maze = np.zeros(maze_size, dtype=np.bool)
  52     for start, end in vector_link:
  53         #print start, end
  54         d1 = start*2
  55         d2 = end*2
  56         middle = start + end
  57         maze[tuple(d1.tolist())] = True
  58         maze[tuple(d2.tolist())] = True
  59         maze[tuple(middle.tolist())] = True
  60     return maze
  61 
  62 def get_next(path, visited, size, DIRS):
  63     """
  64     get what is the next vector?
  65     """
  66     head = path[-1]
  67     #print "head:",head
  68     nextps = [] #store next vectors
  69     for mod in DIRS:
  70         newp = head + mod
  71         #print 'newp:',newp
  72         #out of the scope
  73         out_scope = False
  74         for i, v in enumerate(newp):
  75             if (v<0) or (v>=size[i]): 
  76                 #print newp, v, size[i], size
  77                 out_scope = True
  78                 break
  79         if out_scope:
  80             continue
  81         #have visited
  82         if visited[tuple(newp.tolist())] == True:
  83             # print "visited:",newp
  84             # print visited
  85             continue
  86         nextps.append(newp)
  87     if nextps == []:
  88         return None
  89     #random choose a vector
  90     nextp = nextps[random.randint(0, len(nextps)-1)]
  91     #print "nextps:",nextps
  92     #print "nextp:  ",nextp
  93     return nextp
  94 
  95 def show_maze(maze):
  96     """
  97     print maze to command line.
  98     """
  99     if maze.ndim == 3:
 100         for map in maze:
 101             print
 102             for row in map:
 103                 print "".join(['_'if i else '#' for i in row])
 104     elif maze.ndim == 2:
 105         for row in maze:
 106             print "".join(['_'if i else '#' for i in row])
 107 
 108 def draw_maze(maze):
 109     """
 110     use pygame to render a png file.
 111     """
 112     if maze.ndim != 2: return
 113     try:
 114         import pygame
 115     except:
 116         print "looks like you don't have pygame,"
 117         print "install pygame for rending a image file."
 118     pygame.init()
 119 
 120     DOT = 8
 121     size = maze.shape
 122     sw, sh = size
 123 
 124     surface = pygame.Surface((sw*DOT, sh*DOT))
 125     for i in range(sw):
 126         for j in range(sh):
 127             if maze[i][j] == True:
 128                 surface.fill((200,200,200), 
 129                              pygame.Rect(i*DOT, j*DOT, DOT, DOT))
 130     pygame.image.save(surface, "test.png")
 131 
 132 def main():
 133     maze = create_maze(30, 30, 30)
 134     show_maze(maze)
 135     draw_maze(maze)
 136 
 137 if __name__=="__main__":
 138     main()


反馈

创建 by -- ZoomQuiet [2010-04-16 08:47:44]

MiscItems/2010-04-16 (last edited 2010-04-16 08:47:44 by ZoomQuiet)