1

this article과 같이 프로 시저 생성 던전을 만들려고했습니다. 하지만 이런 종류의 알고리즘을 이해하는 것은 다소 힘든 일이었습니다. 그래서 대신, 나는 적어도 방 배치를 이해하기 위해 가이드로 this을 사용 해왔다.IndexError : 매트릭스에서 범위를 벗어난 색인을 나열하십시오.

이 기사에 사용 된 프로그램은 Java로 작성 되었기 때문에 "현실"에 적응하고 Python 3.5에서 동일한 결과를 에뮬레이트하려고했습니다.

from random import randint 


class Room: 

    """docstring for Room""" 

    def __init__(self, x, y, w, h): 
     """[summary] 

     [description] 

     Arguments: 
       x {int} -- bottom-left horizontal anchorpoint of the room 
       y {int} -- bottom-left vertical anchor point of the room 
       w {int} -- width of the room 
       h {int} -- height of the room 
     """ 
     self.x1 = x 
     self.x2 = x + w 
     self.y1 = y 
     self.y2 = y + h 
     self.w = w 
     self.h = h 
     self.center = ((self.x1 + self.x2)/2, (self.y1 + self.y2)/2) 

    def intersects(self, room): 
     """[summary] 

     Verifies if the rooms overlap 

     Arguments: 
       room {Room} -- a room object 
     """ 
     return(self.x1 <= room.x2 and self.x2 >= room.x1 and \ 
       self.y1 <= room.y2 and self.y2 >= room.y1) 

    def __str__(self): 
     room_info = ("Coords: (" + str(self.x1) + ", " + str(self.y1) + 
        ") | (" + str(self.x2) + ", " + str(self.y2) + ")\n") 
     room_info += ("Center: " + str(self.center) + "\n") 
     return(room_info) 

MIN_ROOM_SIZE = 10 
MAX_ROOM_SIZE = 20 
MAP_WIDTH = 400 
MAP_HEIGHT = 200 
MAX_NUMBER_ROOMS = 20 

dungeon_map = [[None] * MAP_WIDTH for i in range(MAP_HEIGHT)] 
# print(dungeon_map) 


def crave_room(room): 
    """[summary] 

    "saves" a room in the dungeon map by making everything inside it's limits 1 

    Arguments: 
      room {Room} -- the room to crave in the dungeon map 
    """ 
    for x in xrange(min(room.x1, room.x2), max(room.x1, room.x2) + 1): 
     for y in xrange(min(room.y1, room.y2), max(room.y1, room.y2) + 1): 
      print(x, y) # debug 
      dungeon_map[x][y] = 1 
    print("Done") # dungeon 


def place_rooms(): 

    rooms = [] 

    for i in xrange(0, MAX_NUMBER_ROOMS): 
     w = MIN_ROOM_SIZE + randint(0, MAX_ROOM_SIZE - MIN_ROOM_SIZE + 1) 
     h = MIN_ROOM_SIZE + randint(0, MAX_ROOM_SIZE - MIN_ROOM_SIZE + 1) 
     x = randint(0, MAP_WIDTH - w) + 1 
     y = randint(0, MAP_HEIGHT - h) + 1 

     new_room = Room(x, y, w, h) 
     fail = False 
     for other_room in rooms: 
      if new_room.intersects(other_room): 
       fail = True 
       break 
     if not fail: 
      print(new_room) 
      crave_room(new_room) # WIP 
      new_center = new_room.center 
      # rooms.append(new_room) 
      if len(rooms) != 0: 
       prev_center = rooms[len(rooms) - 1].center 

       if(randint(0, 1) == 1): 
        h_corridor(prev_center[0], new_center[0], prev_center[1]) 
        v_corridor(prev_center[1], new_center[1], prev_center[0]) 
       else: 
        v_corridor(prev_center[1], new_center[1], prev_center[0]) 
        h_corridor(prev_center[0], new_center[0], prev_center[1]) 
     if not fail: 
      rooms.append(new_room) 
    for room in rooms: 
     print(room) 


def h_corridor(x1, x2, y): 
    for x in xrange(min(x1, x2), max(x1, x2) + 1): 
     dungeon_map[x][y] = 1 


def v_corridor(y1, y2, x): 
    for y in xrange(min(y1, y2), max(y1, y2) + 1): 
     dungeon_map[x][y] = 1 

place_rooms() 

을하지만 난 그것을 실행할 때마다, 나는 다음과 같은 오류 얻을 : 다음과 같이

내 코드가 내 코드에서 이해 무엇을 위해

Traceback (most recent call last): 
    File "/home/user/dungeon.py", line 114, in <module> 
    place_rooms() 
    File "/home/user/dungeon.py", line 87, in place_rooms 
    crave_room(new_room) 
    File "/home/user/dungeon.py", line 65, in crave_room 
    dungeon_map[x][y] = 1 
IndexError: list index out of range 

을의 crave_room 기능이 제대로 작동합니다 , 왜냐하면 나는 minmax 함수를 사용하고 있기 때문이다. 그리고 h_corridorv_corridor 함수가 비슷한 방식으로 작동하기 때문에 같은 종류의 문제가 발생합니다.

원본 기사에서 사용 된 캔버스의 대체품으로 매트릭스를 사용하고 있기 때문에 문제가 발생하는지 확실하지 않습니다. 로컬/글로벌 변수 문제가 의심 스럽지만 문제라고 생각하지 않습니다. 나는 매우 어리석은 실수를 저지르고 그것을 보지 못하고 있습니다.

사용하기 좋은 데이터 구조에 관한 모든 코드 개선 팁이나 제안을 환영하며 누구나 가지고있는 주제가 더 명확하고 간단한 기사 인 경우 Python을 사용하는 것이 좋습니다. 많은 관련 게시물을 여기에서 보았습니다. 그러나 나는 아직도 잃어 버렸습니다.

도움 주셔서 감사합니다. : D

+5

'dungeon_map = [[없음] * MAP_WIDTH] * MAP_HEIGHT'는 나중에 문제를 일으킬 것입니다. 자세한 내용은 [목록의 파이썬 목록, 예기치 않게 하위 목록에 반영된 변경 사항]을 참조하십시오. http://stackoverflow.com/q/240178/953482 – Kevin

+0

야생 추측 : 한 행/열을 더 크게/크게 만듭니다.'dungeon_map = [[없음] (MAP_HEIGHT + 1) _에 대한 [없음 (MAP_WIDTH + 1)] ' – Kevin

+0

감사합니다. 코드를 업데이트하겠습니다. – inblank

답변

1

당신은 당신의 dungeon_map 잘못 선언이 :

dungeon_map = [[None] * MAP_WIDTH] * MAP_HEIGHT 

올바른 방법이 있어야한다 : 당신이의 두 번째 살펴 보자 것을 다 이제

dungeon_map = [[None] * MAP_HEIGHT] * MAP_WIDTH 

, 더 심각한 문제 . 의 작은 규모 (작은지도)에서 실험 보자 :이 실험에서

MAP_WIDTH = 4 
MAP_HEIGHT = 2 
dungeon_map = [[None] * MAP_HEIGHT] * MAP_WIDTH 

print('\nBefore Assignment:') 
print(dungeon_map) 

dungeon_map[2][1] = 'y' 

print('\nAfter Assignment:') 
print(dungeon_map) 

을, 우리는 4 열 × 2 열 매트릭스를 생성하고 우리는 하나의 셀의 값을 변경, 그래서 출력을 살펴 보자 :

Before Assignment: 
[[None, None], [None, None], [None, None], [None, None]] 

After Assignment: 
[[None, 'y'], [None, 'y'], [None, 'y'], [None, 'y']] 

무슨 일입니까? 본질적으로 동일한 목록 인 MAP_WIDTH 번을 선언합니다. 이다

dungeon_map = [[None] * MAP_HEIGHT] * MAP_WIDTH 

올바른 방법은 매트릭스를 선언 할 : 아래의 선언 라인은 편리하고 영리하지만 잘못

dungeon_map = [[None for x in range(MAP_HEIGHT)] for y in range(MAP_WIDTH)] 
아마 당신의 문제와 관련이 있지만
+0

답변을 주셔서 감사합니다. 주소 지정 문제에 대해 알지 못했습니다. 이제 코드를 개선하고 최적화 할 것입니다. – inblank