Pergunta

Eu preciso ter um raio de 2 mapa de tirar o jogador da sala atual em uma LAMA estou construindo em python (ou mais, se possível).Os quartos são definidos como recipientes com um self.exits = {'west':1, 'north':2} onde a chave é a direção que o valor (UID da sala ao lado) está localizado.Os quartos estão ligadas apenas desta forma.Um jogador com um auto.localização de 0 pode digitar 'n' e a sua localização, com base na variável acima, seria, então, 2 e que a sala de conteúdo teria o jogador UID acrescentado ao seu conteúdo.

Então, eu gostaria de ter um mapa exibida semelhante à seguinte, com base na variável acima, onde " u " é o jogador do atual localização..

    [ ]
     |
[ ]-[u]

Consegui este parte, como este é apenas um raio de 1.Aqui está uma pequena (fortemente modificadas para postar aqui) fragmento de como eu fiz isso, e você vai ver por que eu estou postando, como é ruim código.

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)

Na minha loucura, eu consegui fazer esse trabalho com todas as 8 direções diferentes (diagonais, e não incluindo o para cima ou para baixo).Mas eu, então, necessário para o ciclo quartos eu só analisados com o meu primeiro loop e, em seguida, desenhe os e, em seguida, o espaço é de todos para fora e, em seguida, levar em conta a sobreposição dos (sp)ases como um '\' ou '|' se há caminhos que se cruzam.Esta pequena tarefa virou pesadelo imediatamente, e bem em 200 linhas antes eu tinha feito.

Outro obstáculo é que eu só posso imprimir linha por linha.Então, se o mapa é de 50 caracteres alta, eu tenho que ter player.hear() em 50 linhas, que eu não sou oposição.Apenas mantenha isso em mente antes de postar uma resposta.

Eu também não sou exigente quanto a formatação.Eu simplesmente quer um 'mapa de relance' para a ajuda os jogadores enquanto viaja ao redor do mundo.

Obrigado, rapazes.Espero que eu fornecida informação suficiente.Deixe-me saber, se não.(Aqui está um link para o todo (inacabada e HORRÍVEL) módulo eu estou fazendo referência. Map.py

Foi útil?

Solução

Este código está em sérios apuros.Vamos começar a desenhar a partir do zero.Esperamos que possa servir como uma boa aula de como projetar e construir classes e estruturas de dados.

Para começar, você deve organizar seu código em torno de uma Map classe, que representa os seus quartos como uma grade.Você não deve pensar em "sala 1", "sala 2", etc (o que é muito difícil acompanhar em um mapa), e, ao invés de pensar quartos em termos de coordenadas.

Agora, há algumas características que são ignorando no início, incluindo o jogador ver apenas os quartos que ele foi para o jogador a permanecer no centro do mapa, e diagonal caminhos.Se desejar, você pode colocá-los mais tarde, uma vez que a funcionalidade básica de obras.Para agora, nós estamos apontando para algo que parece um pouco como este:

[ ]-[u] [ ] [ ]
 |
[ ]-[ ]-[ ] [ ]
     |
[ ]-[ ]-[ ] [ ]
 |
[ ]-[ ]-[ ]-[ ]

Isto é, estamos representando-o como uma grade, onde alguns quartos estão ligados e os outros não são.Vamos ter cada quarto tem um par de coordenadas, um pouco como este:

      0   1   2   3
   0 [ ]-[u] [ ] [ ]
      |
   1 [ ]-[ ]-[ ] [ ]
          |
   2 [ ]-[ ]-[ ] [ ]
      |
   3 [ ]-[ ]-[ ]-[ ]

Deixe x ser ao longo da parte superior e y ser ao longo do lado.A parte superior esquerda é (0, 0); com [u] em é (0, 1).

Agora, quais são os componentes de nossa Map classe?

  1. mapa de altura:inteiro

  2. mapa de largura:inteiro)

  3. player_x, player_y:coordenadas do jogador

  4. caminhos possíveis:uma lista de pares de quartos que podem se mover entre.O mapa acima poderia ser representado como:

    [((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))]
    

Repare que eu pedi a cada par de tal forma que a maior tupla vai em primeiro lugar (isso é importante mais tarde).

Então, agora que temos o nosso projeto, vamos escrever que Map classe!

Eu posso pensar de quatro métodos queremos: print_map, move, e um inicializador.Intitialization é simples:basta definir os quatro atributos que listamos acima:

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

Agora, move é bastante simples.Dada uma direção 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

O move função para "norte" apenas verifica se existe um caminho para a sala de cima o que nós estamos.

Agora para a parte mais interessante:imprimir o mapa.Você pode fazer isso pelo loop sobre as linhas (de 0 a self.height) e as colunas (0 a self.width). (Nota:você não pode usar print nesta situação, pois coloca automaticamente uma nova linha ou espaço após a seqüência de caracteres.Em vez disso, use sys.stdout.escrever.

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

Agora vamos colocar tudo isso junto e experimentá-lo.Aqui está o código:

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)

Observe que eu adicionada uma seção sobre o inferior, o que cria um mapa e permite ao jogador mover-se em torno dele.Aqui está como ele olha quando ele é executado:

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] [ ] 
     |          
[ ]-[ ]-[ ] [ ] 
 |              
[ ]-[ ]-[ ]-[ ] 

Há muitas melhorias que podem ser feitas a este código (em particular, o move o método é repetitivo), mas é um bom começo.Tente fazer o mapa 20x20 e você vai ver que se expande muito bem.

ETA:Devo observar que print_map poderia ser reescrito, em uma forma mais curta algo como:

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)])

Mas este é um pouco mais intensa.

Outras dicas

Eu fiz isso como um exercício onde os quartos e a grade de "imprima-se".Eu acrescentar à discussão, já que pode ser mais fácil de implementar com um eventual grade maior.

O ASCII Mapa

+++++++++++++++
+++++++++++++++
+++++++++++++++
++++++   ++++++
++++++ 2 ++++++
++++++/| ++++++
+++  / | ++++++
+++ 3--1 ++++++
+++     \++++++
+++++++++\  +++
+++++++++ 4 +++
+++++++++   +++
+++++++++++++++
+++++++++++++++
+++++++++++++++

Cada célula na grade é um três por três conjunto de '+' sinais.Quatro quartos são implementados com o valor de id de 1 a 4.Conexões entre os quartos são representadas como barras, barras invertidas e tubos.

O Código

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

O movimento de rotina não está implementado, e para esta representação para o trabalho, somente o caractere ids vai mostrar-se muito bem.

As vantagens deste sistema:

  • fácil adicionar os quartos e para removê-los
  • a definição de um quarto é legível para humanos
  • as funções de saída de sobrecarga __str__ e, portanto, quartos e grade "imprimir" e isso pode vir a ser útil para depuração futuras ou adaptação para futuros formatos e.g.como as células em uma tabela HTML.

Coordenar mapas tem um monte de vantagens, mas, considerando que muitos de qualidade lamas de usar uma sala tradicional baseado no mundo, e as pessoas têm feito automappers por muitos lamas e lodos de clientes, ela não está fora de questão fazer um automap para uma lama sem coordenadas.Você só vai ter que lidar com conflitos em uma base de caso a caso.

No entanto, você ainda pode usar a resposta por @david-robinson.O que você quer fazer é manter um minimapa aproximadamente centrada no leitor e dinamicamente a atualização usando a saída de dados.Não tente manter um mapa de toda a área armazenados;por dinamicamente a atualização, você vai evitar alguns geográfica conflitos.

Para escrever o mapa de lama cliente, tudo o que você precisa fazer é escrever a sua linha de mapa devidamente espaçadas e finalizá-lo com uma nova linha.Você coloca tudo o mapa de linhas em uma lista, então é enviado como um único grupo de linhas (você não quer alguma outra linha inserida entre linhas do mapa, por exemplo, quando ele enviou o socket), e qualquer lama cliente irá imprimi-lo corretamente (com um tipo de letra não proporcional, é claro).

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top