Python绘制ASCII映射

Python绘制ASCII映射,python,python-2.7,mud,online-game,Python,Python 2.7,Mud,Online Game,我需要在我正在用python(或者更多,如果可能的话)构建的泥地中,从玩家当前的房间绘制一张2半径的地图。房间设置为带有self.exits={'west':1,'north':2}的容器,其中键是值(相邻房间的UID)所在的方向。房间仅以这种方式链接。self.location为0的播放机可以键入“n”,根据上述变量,它们的位置将为2,并且该房间的内容将附加播放机的UID 因此,我希望根据上述变量,显示一张如下所示的地图,其中“u”是玩家的当前位置 [ ] | [ ]-[u]

我需要在我正在用python(或者更多,如果可能的话)构建的泥地中,从玩家当前的房间绘制一张2半径的地图。房间设置为带有
self.exits={'west':1,'north':2}
的容器,其中键是值(相邻房间的UID)所在的方向。房间仅以这种方式链接。self.location为0的播放机可以键入“n”,根据上述变量,它们的位置将为2,并且该房间的内容将附加播放机的UID

因此,我希望根据上述变量,显示一张如下所示的地图,其中“u”是玩家的当前位置

    [ ]
     |
[ ]-[u]
我已经得到了这个部分,因为它的半径是1。这里有一个关于我是如何做到这一点的小片段(在这里发布时进行了大量修改),您将看到我发布的原因,因为这是糟糕的代码

mloc = '[u]'
mn = '   '
mw = '   '
spn= ' '
spw= ' '
for Exit in room.exits.keys():
  if Exit == 'north':
    mn = '[ ]'
    spn = '|'
  if Exit == 'west': 
    mw = '[ ]-'
# player.hear() is our function for printing a line to the player's screen
player.hear('    '+mn)
player.hear('     '+sp)
player.hear(mw+mloc)
在我精神错乱的时候,我设法用所有8个不同的方向(对角线,不包括向上或向下)来完成这项工作。但是我必须对我刚刚用我的第一个for循环解析的房间进行for循环,然后绘制这些房间,然后将其全部隔开,然后考虑(sp)ace的重叠,例如“\”或“|”,如果存在相互交叉的路径。这个小小的任务立刻变成了噩梦,在我完成之前已经排了200行了


另一个障碍是我只能逐行打印。因此,如果地图有50个字符高,我必须在50行上有
player.hear()
,我并不反对。在发布答案之前,请记住这一点

我对格式也不挑剔。我只是想要一张“地图一目了然”来帮助玩家周游世界

谢谢各位。我希望我提供了足够的信息。如果没有,请告诉我。
(这里是我引用的整个(未完成且可怕)模块的链接。

这段代码遇到了严重问题。让我们从头开始设计。这有望成为如何设计和构建类和数据结构的一堂好课

首先,您应该围绕
Map
类组织代码,然后将房间表示为网格。您不应该考虑“房间1”、“房间2”等(这在地图上很难跟踪),而应该考虑房间的坐标

现在,我们在开始时忽略了一些可能的功能,包括只看到他去过的房间的玩家、留在地图中心的玩家以及对角线路径。如果您需要这些功能,可以在基本功能正常后将其放入。现在,我们的目标是类似以下内容:

[ ]-[u] [ ] [ ]
 |
[ ]-[ ]-[ ] [ ]
     |
[ ]-[ ]-[ ] [ ]
 |
[ ]-[ ]-[ ]-[ ]
      0   1   2   3
   0 [ ]-[u] [ ] [ ]
      |
   1 [ ]-[ ]-[ ] [ ]
          |
   2 [ ]-[ ]-[ ] [ ]
      |
   3 [ ]-[ ]-[ ]-[ ]
也就是说,我们将其表示为一个网格,其中一些房间是连接的,而其他房间不是。让我们让每个房间都有一个坐标对,有点像这样:

[ ]-[u] [ ] [ ]
 |
[ ]-[ ]-[ ] [ ]
     |
[ ]-[ ]-[ ] [ ]
 |
[ ]-[ ]-[ ]-[ ]
      0   1   2   3
   0 [ ]-[u] [ ] [ ]
      |
   1 [ ]-[ ]-[ ] [ ]
          |
   2 [ ]-[ ]-[ ] [ ]
      |
   3 [ ]-[ ]-[ ]-[ ]
让x沿顶部,y沿侧面。左上角是(0,0),其中带有
[u]
的是(0,1)

现在,我们的
Map
类的组件是什么

  • 地图高度:整数

  • 地图宽度:整数)

  • 游戏者x,游戏者y:游戏者的坐标

  • 可能路径:我们可以在其中移动的成对房间的列表。上述地图将表示为:

    [((0, 0), (1, 0)), ((0, 0), (1, 0)), ((1, 0), (1, 1)), ((1, 1), (2, 1)),
     ((1, 0), (1, 2)), ((0, 2), (1, 2)), ((1, 2), (2, 2)), ((0, 2), (0, 3)),
     ((0, 3), (1, 3)), ((1, 3), (2, 3)), ((2, 3), (3, 3))]
    
  • 请注意,我对每一对进行了排序,以使较大的元组优先(这在后面很重要)

    现在我们有了我们的设计,让我们来编写
    Map

    我可以想出我们想要的四种方法:
    print\u map
    move
    ,以及初始值设定项。初始化很简单:只需设置上面列出的四个属性:

    class Map:
        def __init__(self, height, width, player_x, player_y, paths):
            self.height = height
            self.width = width
            self.x = player_x
            self.y = player_y
            self.paths = paths
    
    现在,
    move
    非常简单。给定方向n/e/s/w:

        def move(self, direction):
            if direction == "n":
                if ((self.x, self.y - 1), (self.x, self.y)) not in self.paths:
                    print "Cannot go north"
                else:
                    self.y -= 1
    
    “北”的
    move
    功能只是检查我们所在房间上方是否有通往房间的路径

    现在来看最有趣的部分:打印地图。您可以通过在行(0到
    self.height
    )和列(0到
    self.width
    )上循环来实现这一点。(注意:在这种情况下,您不能使用
    print
    ,因为它会自动在字符串后添加换行符或空格。我们使用

    现在,让我们把它们放在一起,并尝试一下。下面是代码:

    import sys
    
    class Map:
        def __init__(self, height, width, player_x, player_y, paths):
            self.height = height
            self.width = width
            self.x = player_x
            self.y = player_y
            self.paths = paths
    
        def move(self, direction):
            if direction == "n":
                if ((self.x, self.y - 1), (self.x, self.y)) not in self.paths:
                    print "Cannot go north"
                else:
                    self.y -= 1
            if direction == "s":
                if ((self.x, self.y), (self.x, self.y + 1)) not in self.paths:
                    print "Cannot go south"
                else:
                    self.y += 1
            if direction == "e":
                if ((self.x, self.y), (self.x + 1, self.y)) not in self.paths:
                    print "Cannot go east"
                else:
                    self.x += 1
            if direction == "w":
                if ((self.x - 1, self.y), (self.x, self.y)) not in self.paths:
                    print "Cannot go west"
                else:
                    self.x -= 1
    
        def print_map(self):
            for y in range(0, self.height):
                # print the yth row of rooms
                for x in range(0, self.width):
                    if self.x == x and self.y == y:
                        sys.stdout.write("[u]")  # this is the player's room
                    else:
                        sys.stdout.write("[ ]")  # empty room
                    # now see whether there's a path to the next room
                    if ((x, y), (x + 1, y)) in self.paths:
                        sys.stdout.write("-")
                    else:
                        sys.stdout.write(" ")
                # now that we've written the rooms, draw paths to next row
                print  # newline
                for x in range(0, self.width):
                    sys.stdout.write(" ")  # spaces for above room
                    if ((x, y), (x, y + 1)) in self.paths:
                        sys.stdout.write("|  ")
                    else:
                        sys.stdout.write("   ")
                print
    
    
    paths = [((0, 0), (1, 0)), ((0, 0), (1, 0)), ((1, 0), (1, 1)), ((1, 1),
             (2, 1)), ((1, 1), (1, 2)), ((0, 2), (1, 2)), ((1, 2), (2, 2)),
             ((0, 2), (0, 3)), ((0, 3), (1, 3)), ((1, 3), (2, 3)), ((2, 3),
             (3, 3))]
    m = Map(4, 4, 0, 0, paths)
    
    while True:
        m.print_map()
        direction = raw_input("What direction do you want to move? [n/e/s/w] ")
        m.move(direction)
    
    请注意,我在底部添加了一个部分,用于创建地图并允许玩家在地图周围移动。下面是它运行时的外观:

    Davids-MacBook-Air:test dgrtwo$ python Map.py 
    [u]-[ ] [ ] [ ] 
         |          
    [ ] [ ]-[ ] [ ] 
         |          
    [ ]-[ ]-[ ] [ ] 
     |              
    [ ]-[ ]-[ ]-[ ] 
    
    What direction do you want to move? [n/e/s/w] e
    [ ]-[u] [ ] [ ] 
         |          
    [ ] [ ]-[ ] [ ] 
         |          
    [ ]-[ ]-[ ] [ ] 
     |              
    [ ]-[ ]-[ ]-[ ] 
    
    What direction do you want to move? [n/e/s/w] s
    [ ]-[ ] [ ] [ ] 
         |          
    [ ] [u]-[ ] [ ] 
         |          
    [ ]-[ ]-[ ] [ ] 
     |              
    [ ]-[ ]-[ ]-[ ] 
    
    What direction do you want to move? [n/e/s/w] w
    Cannot go west
    [ ]-[ ] [ ] [ ] 
         |          
    [ ] [u]-[ ] [ ] 
         |          
    [ ]-[ ]-[ ] [ ] 
     |              
    [ ]-[ ]-[ ]-[ ] 
    
    What direction do you want to move? [n/e/s/w] e
    [ ]-[ ] [ ] [ ] 
         |          
    [ ] [ ]-[u] [ ] 
         |          
    [ ]-[ ]-[ ] [ ] 
     |              
    [ ]-[ ]-[ ]-[ ] 
    
    可以对此代码进行许多改进(特别是,
    move
    方法是重复的),但这是一个很好的开始。尝试制作20x20贴图,您会看到它展开得很好

    ETA:我应该注意到,
    print\u map
    可以用更短的形式重写,如下所示:

    def print_map(self):
        for y in range(0, self.height):
            print "".join(["[%s]%s" %
                        ("u" if self.x == x and self.y == y else " ",
                         "-" if ((x, y), (x + 1, y)) in self.paths else " ")
                            for x in range(0, self.width)])
            print " " + "   ".join(["|" if ((x, y), (x, y + 1)) in self.paths
                                  else " " for x in range(0, self.width)])
    

    但这有点紧张。

    我这样做是为了练习房间和网格“打印自己”。我将此添加到讨论中,因为使用最终更大的网格可能更容易实现

    ASCII映射 此网格中的每个单元格都是一组三乘三的“+”符号。四个房间的id值为1到4。房间之间的连接表示为斜线、反斜线和管道

    代码 移动例程没有实现,为了使这种表示有效,只有单字符ID才能很好地显示出来

    该系统的优点:

    • 易于添加和删除房间
    • 房间的定义是人类可读的
    • 输出函数重载
      \uuuu str\uuuu
      ,因此文件室和网格“自行打印”,这可能有助于将来调试或适应未来格式,例如HTML表格中的单元格

    基于坐标的地图有很多优点,但考虑到许多高质量的mud使用传统的基于房间的世界,并且人们已经为许多mud和mud客户制作了自动地图,为没有坐标的mud制作自动地图并非不可能。您只需根据具体情况处理冲突

    class Room(object):
        def __init__(self, id, loc, exits):
            self.id = id # unique identifier, may be a name
            self.row = loc[0] # loc is tuple of (row, col)
            self.col = loc[1] 
            # exits is a list where 'X' means no exit and 
            # any other value is id of destination
            self.exits = exits 
    
        def __str__(self):
            directions = '\\|/- -/|\\'
            room = [ e if e == 'X' else ' ' for e in self.exits ]
            for idx in range(len(room)):
                if room[idx] == ' ':
                    room[idx] = directions[idx]
                if room[idx] == 'X':
                    room[idx] = ' '
            room[4] = self.id[0] # only print first char of id
            return ''.join(room)
    
    class Map(object):
        def __init__(self, rows, cols, rooms):
            self.rows = rows
            self.cols = cols
            self.rooms = rooms
    
        def __str__(self):
            world = []
            for i in range(self.rows * 3):
                world.append( ['+++'] * self.cols )
            for room in self.rooms:
                ascii = str(room)
                x = room.col
                y = room.row
                for idx in range(0, 3):
                    cell = ascii[idx*3:idx*3+3]
                    world[y*3+idx][x] = cell
            return '\n'.join( [ ''.join(row) for row in world ] )
    
    
    if __name__ == '__main__':
        # set up four rooms
        # each room has unique id (string of any length) and coordinates
        # it also has a set of 8 possible exits, represented as a list where
        # 'X' means exit is blocked and valid exits contain the id of the target room
        r1 = Room(id='1', loc=(2,2), exits=['X','2','X',
                                            '3',' ','X',
                                            'X','X','4',])
        r2 = Room(id='2', loc=(1,2), exits=['X','X','X',
                                            'X',' ','X',
                                            '3','1','X',])
        r3 = Room(id='3', loc=(2,1), exits=['X','X','2',
                                            'X',' ','1',
                                            'X','X','X',])
        r4 = Room(id='4', loc=(3,3), exits=['1','X','X',
                                            'X',' ','X',
                                            'X','X','X',])
        # initialize Map with a list of these four rooms
        map = Map(rows = 5, cols=5, rooms=[r1, r2, r3, r4])
        print map