문제

나는 파이썬(가능한 경우 또는 그 이상)으로 만들고 있는 진흙 속에서 플레이어의 현재 방에서 2 반경 지도를 그려야 합니다.객실은 컨테이너로 구성되어 있습니다. self.exits = {'west':1, 'north':2} 여기서 키는 값이 있는 방향입니다.객실은 이런 식으로 만 연결되어 있습니다.자아를 가진 선수0 의 위치는'엔'을 입력할 수 있고,위의 변수에 따라 그 위치는 2 가 될 것이고,그 방의 내용은 플레이어의 유이드가 그 내용에 첨부될 것입니다.

그래서,나는'유'는 플레이어의 현재 위치 인 위의 변수에 따라 다음과 같이 보이는 맵을 표시하고 싶습니다..

    [ ]
     |
[ ]-[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 개의 다른 방향(대각선,그리고 위 또는 아래를 포함하지 않음)으로이 작업을 할 수있었습니다.그러나 나는 루프에 대해 내가 처음 루프에 대해 구문 분석 한 방을 루프에 대해 다음 루프를 그린 다음 공간을 모두 뺀 다음 서로 교차하는 경로가있는 경우'\'또는'|'와 같은 에이스의 겹침을 고려해야합니다.이 작은 작업은 내가 완료되기 전에 즉시 악몽,그리고 잘 200 줄로 바뀌 었습니다.

또 다른 장애물은 한 줄씩 인쇄 할 수 있다는 것입니다.그래서 지도가 50 자 높다면,나는 player.hear() 50 개의 라인을 가지고 있는데,저는 반대하지 않습니다.그냥 대답을 게시 하기 전에 마음에 계속.

나는 또한 포맷에 대해 까다 롭지 않다.난 그냥 단순히 전 세계를 여행하는 동안 플레이어를 돕기 위해'한 눈에 맵'을 할 수 있습니다.

고마워 얘들 아.충분한 정보를 제공했으면 좋겠습니다.그렇지 않다면 알려주세요.(여기에 내가 참조하고있는 전체(미완성 및 끔찍한)모듈에 대한 링크가 있습니다. Map.py

도움이 되었습니까?

해결책

이 코드에서는 심각한 문제입니다.자의 디자인을 시작 처음부터.이것은 역할을 희망으로 좋은 교훈을 디자인하는 방법과 클래스를 구축 및 데이터 구조입니다.

을 시작으로 정리해야 합니다 당신의 코드 주변 Map 클래스에는 다음을 나타내는 객실니다.당신이 생각하지 말아야에 대해"객실 1","객실이 2",etc.(입을 유지하기 위해 매우 열심히 노력을 추적의 지도에서),및 오히려 생각의 객실 측면에서 좌표입니다.

지금,거기에 몇 가지 기능을 우리는 무시 시작 부분에 포함하여 플레이어만 객실에는 그는 플레이어에서 나머지 지도의 중심,그리고 대각선이 경로입니다.당신이 그들을 원하는 경우 당신은 그들을 둘 수 있에서,나중에 일단 기본적인 기능이 작동합니다.지금,우리는 무엇인가를 목표로 보이는 조금 다음과 같다:

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

즉,우리는 그것을 대표적으로 그리드는 대부분의 객실 연결되어 있고 다른 사람은 없습니다.자가 각 객실에는 좌표 쌍,작은 다음과 같다:

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

Let x 될 상단 및 y 함께 할 수있다.쪽(0,0)나 [u] 그것은(0,1)입니다.

지금이 무엇인지,구성 요소의 Map 등?

  1. 지도 높이:정수

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

통지는 내가 주문한 각 쌍에는 더 큰 tuple 가(는 것이 중요 나중에).

그래서 지금 우리는 우리의 디자인,쓰자는 Map 클래스!

나는 생각할 수 있는 네 가지 방법을 우리가 원하는: print_map, move, 하고,이니셜라이저입니다.Intitialization 는 간단하다:그냥 설정은 네 가지 특성이 우리 위에 나열된:

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 이 상황에서부터 자동으로 줄 바꿈이나 뒤에 공백 문자열입니다.대신에 우리가 사용하는 sys.stdout.쓰.

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

지금,그것을 모두 함께 그것을 밖으로보십시오.여기에는 코드:

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 방법은 반복)하지만,그것은 잘 시작합니다.를 만드는 시도하지도 20×20 고 당신은 그것을 볼 확장됩니다.

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

하지만 이것이 조금 더 강렬하다.

다른 팁

나는 방 및 격자가"인쇄하는 연습으로 이것을"했다.나는 궁극적으로 더 큰 그리드로 구현하는 것이 더 쉬울 수 있으므로 토론에 이것을 추가합니다.

아스키 지도

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

이 그리드의 각 셀은'+'기호 세 세트입니다.4 개의 방이 1 부터 4 까지의 아이디로 구현되어 있습니다.방 사이의 연결은 슬래시,백 슬래시 및 파이프로 표시됩니다.

코드

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

이동 루틴은 구현되지 않으며,이 표현이 작동하려면 단일 문자 신분증 만 멋지게 표시됩니다.

이 시스템의 장점:

  • 쉽게 객실을 추가하고 그들을 제거 할 수 있습니다
  • 방의 정의는 사람이 읽을 수 있습니다.
  • 출력 함수 과부하 __str__ 따라서 룸과 그리드는"스스로 인쇄"되고 이것은 미래의 디버깅이나 미래의 형식에 대한 적응에 유용 할 수 있습니다.표에 있는 셀로

좌표 기반지도에는 많은 이점이 있지만 많은 품질의 진흙이 전통적인 실내 기반의 세계를 사용하고 사람들은 많은 진흙과 진흙 클라이언트를 위해 자동차 패배를 만들었습니다. 좌표가없는 진흙. 사례별로 충돌을 다루어야합니다.

그러나 @ David-Robinson의 답변을 여전히 사용할 수 있습니다. 당신이하고 싶은 것은 미니 맵을 플레이어에 대략 중심으로 유지하고 종료 데이터를 사용하여 동적으로 업데이트하는 것입니다. 전체 영역의지도를 유지하려고하지 마십시오. 동적으로 업데이트하면 지리적 충돌이 발생하지 않습니다.

맵을 진흙 클라이언트에 기록하기 위해서는지도 선을 제대로 이격시키고 새로운 줄로 종료하는 것입니다. 모든지도 줄을 목록에 넣으므로 단일 라인 그룹으로 전송하므로 소켓을 보낼 때 맵의 줄 사이에 삽입되지 않아야합니다. 진흙 클라이언트가 인쇄됩니다. 적절하게 (물론 모노 스페이스 글꼴로).

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top