Python绘图ASCII地图

jts*_*287 6 python mud online-game python-2.7

我需要在我正在使用python构建的MUD(或者更多,如果可能的话)中从玩家的当前房间中抽取2个半径图.房间设置为容器,self.exits = {'west':1, 'north':2}其中键是值(相邻房间的UID)所在的方向.客房仅以这种方式相连.self.location为0的玩家可以键入'n',并且基于上面的变量,他们的位置将是2,并且该房间的内容将玩家的UID附加到其内容.

所以,我希望根据上面的变量显示一个如下所示的地图,其中'u'是玩家的当前位置.

    [ ]
     |
[ ]-[u]
Run Code Online (Sandbox Code Playgroud)

我已经实现了这一部分,因为这只是一个半径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)
Run Code Online (Sandbox Code Playgroud)

在我疯狂的情况下,我成功地完成了所有8个不同方向的工作(对角线,不包括向上或向下).但是我必须循环使用我的第一个for循环解析的房间,然后绘制它们,然后将它全部分开,然后考虑(sp)aces的重叠,例如'\'或' |" 如果有相互交叉的路径.这个小小的任务立刻变成了噩梦,在我完成之前已经进入了200行.

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

我对格式化也不挑剔.我只想简单地想要一张"地图一览"来帮助玩家环游世界.

多谢你们.我希望我提供了足够的信息.如果没有,请告诉我.(这是我正在引用的整个(未完成和可怕的)模块的链接.Map.py

Dav*_*son 12

这段代码很麻烦.让我们从头开始设计.这有望成为如何设计和构建类和数据结构的一个很好的教训.

首先,您应该围绕一个Map类来组织代码,然后将您的房间表示为网格.你不应该考虑"房间1","房间2"等(这很难在地图上跟踪),而是考虑坐标方面的房间.

现在,我们在开始时忽略了一些可能的功能,包括玩家只看到他去过的房间,玩家留在地图的中心,以及对角线路径.如果你想要它们,你可以在基本功能工作后将它们放入.目前,我们的目标是看起来像这样:

[ ]-[u] [ ] [ ]
 |
[ ]-[ ]-[ ] [ ]
     |
[ ]-[ ]-[ ] [ ]
 |
[ ]-[ ]-[ ]-[ ]
Run Code Online (Sandbox Code Playgroud)

也就是说,我们将它表示为一个网格,其中一些房间是连接的,而另一些房间则没有.让每个房间都有一个坐标对,有点像这样:

      0   1   2   3
   0 [ ]-[u] [ ] [ ]
      |
   1 [ ]-[ ]-[ ] [ ]
          |
   2 [ ]-[ ]-[ ] [ ]
      |
   3 [ ]-[ ]-[ ]-[ ]
Run Code Online (Sandbox Code Playgroud)

设x沿顶部,y沿侧面.左上角是(0,0),其中的一个[u]是(0,1).

现在,我们Map班级的组成部分是什么?

  1. map height:整数

  2. 地图宽度:整数)

  3. player_x,player_y:玩家的坐标

  4. 可能的路径:我们可以在其间移动的一对房间列表.上面的地图将表示为:

    [((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))]
    
    Run Code Online (Sandbox Code Playgroud)

请注意,我订购了每对,以便更大的元组先行(后来这很重要).

所以现在我们有了自己的设计,让我们写下这Map堂课吧!

我能想到的,我们希望四种方法:print_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
Run Code Online (Sandbox Code Playgroud)

现在,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
Run Code Online (Sandbox Code Playgroud)

move"north" 的功能只是检查我们所在的房间上方是否有通往该房间的路径.

现在是最有趣的部分:打印地图.您可以通过循环遍历行(0到self.height)和列(0到self.width)来完成此操作.(注意:你不能print在这种情况下使用,因为它会自动在字符串后面添加换行符或空格.而是使用sys.stdout.write.

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
Run Code Online (Sandbox Code Playgroud)

现在,让我们把它们放在一起然后尝试一下.这是代码:

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)
Run Code Online (Sandbox Code Playgroud)

请注意,我在底部添加了一个创建地图的部分,并允许玩家在其周围移动.以下是它运行时的外观:

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] [ ] 
     |          
[ ]-[ ]-[ ] [ ] 
 |              
[ ]-[ ]-[ ]-[ ] 
Run Code Online (Sandbox Code Playgroud)

可以对此代码进行许多改进(特别是,该move方法是重复的),但这是一个良好的开端.尝试制作地图20x20,你会发现它扩展得很好.

ETA:我应该注意到,print_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)])
Run Code Online (Sandbox Code Playgroud)

但这有点激烈.