Вызов функции внутри функции не работает должным образом? - PullRequest
0 голосов
/ 07 мая 2018

Я разрабатываю генератор лабиринта на python и имею различные функции для разных этапов процесса. (Я знаю, что код, безусловно, можно улучшить, но я сначала ищу ответ на свою проблему, прежде чем приступить к его оптимизации)

первая функция генерирует базовый лабиринт в виде 2D-списка и работает как положено:

def base_maze(dimension):
    num_rows = int((2 * dimension[1]) + 1)          #number of rows / columns
    num_columns = int((2 * dimension[0]) + 1)       #from tuple input

    zero_row = []                                   #initialise a row of 0s
    for i in range(num_columns):
        zero_row.append(0)

    norm_row = []                                   #initialise a row of
    for i in range(num_columns // 2):               #alternating 0s and 1s
        norm_row.extend([0,1])
    norm_row.append(0)

    maze = []                                       #initialise maze
                                                    #(combination of zero rows 
    for i in range(num_rows  // 2):                 # and normal rows)
        maze.append(zero_row)
        maze.append(norm_row)
    maze.append(zero_row)

    return maze

Другая функция получает соседей выбранной ячейки, а также работает, как и ожидалось:

def get_neighbours(cell, dimension):

    y = cell[0]                                     #set x/y values
    max_y = dimension[0] - 1                        #for reference

    x = cell[1]
    max_x = dimension[1] - 1

    n = (x, y-1)                                    #calculate adjacent
    e = (x+1, y)                                    #coordinates
    s = (x, y+1)
    w = (x-1, y)

    if y > max_y or y < 0 or x > max_x or x < 0:        #check if x/y
        raise IndexError("Cell is out of maze bounds")  #in bounds

    neighbours = []

    if y > 0:                                       #add cells to list
        neighbours.append(n)                        #if they're valid
    if x < max_x:                                   #cells inside maze
        neighbours.append(e)
    if y < max_y:                                   
        neighbours.append(s)
    if x > 0:                                       
        neighbours.append(w)

    return neighbours

следующая функция удаляет стену между двумя заданными ячейками:

def remove_wall(maze, cellA, cellB):

    dimension = []
    x_dim = int(((len(maze[0]) - 1) / 2))           #calc the dimensions
    y_dim = int(((len(maze) - 1) / 2))              #of maze matrix (x,y)
    dimension.append(x_dim)
    dimension.append(y_dim)

    A_loc = maze[2*cellA[1]-1][2*cellA[0]-1]
    B_loc = maze[2*cellB[1]-1][2*cellB[0]-1]

    if cellB in get_neighbours(cellA, dimension):   #if cell B is a neighbour

        if cellA[0] == cellB[0] and cellA[1] < cellB[1]:            #if the x pos of A is equal
            adj_wall = maze[(2*cellA[0]+1)][2*cellA[1]+1+1] = 1     #to x pos of cell B and the y pos
                                                                    #of A is less than B (A is below B)
        elif cellA[0] == cellB[0] and cellA[1] > cellB[1]:          #the adjacent wall is set to 1 (removed)
            adj_wall = maze[(2*cellA[0]+1)][2*cellA[1]+1-1] = 1
                                                                    #same is done for all other directions
        if cellA[1] == cellB[1] and cellA[0] < cellB[0]:
            adj_wall = maze[(2*cellA[0]+1)+1][(2*cellA[1]+1)] = 1

        elif cellA[1] == cellB[1] and cellA[0] > cellB[0]:
            adj_wall = maze[(2*cellA[0]+1-1)][(2*cellA[1]+1)] = 1

        return maze

Тем не менее, когда я пытаюсь объединить эти функции в одну заключительную функцию для построения лабиринта, они не работают, как работают самостоятельно, например:

def test():
    maze1 = base_maze([3,3])
    maze2 = [[0, 0, 0, 0, 0, 0, 0], [0, 1, 0, 1, 0, 1, 0], [0, 0, 0, 0, 0, 0, 0], [0, 1, 0, 1, 0, 1, 0], [0, 0, 0, 0, 0, 0, 0], [0, 1, 0, 1, 0, 1, 0], [0, 0, 0, 0, 0, 0, 0]]

    if maze1 == maze2:
        print("they are exactly the same")
    else:
        print("WHY ARE THEY DIFFERENT???")

    remove_wall(maze1,(0,0),(0,1))
    remove_wall(maze2,(0,0),(0,1))

они будут давать разные результаты, несмотря на то, что входные данные абсолютно одинаковы?:

test()
they are exactly the same
[[0, 0, 0, 0, 0, 0, 0], [0, 1, 1, 1, 0, 1, 0], [0, 0, 0, 0, 0, 0, 0], [0, 1, 1, 1, 0, 1, 0], [0, 0, 0, 0, 0, 0, 0], [0, 1, 1, 1, 0, 1, 0], [0, 0, 0, 0, 0, 0, 0]]
[[0, 0, 0, 0, 0, 0, 0], [0, 1, 1, 1, 0, 1, 0], [0, 0, 0, 0, 0, 0, 0], [0, 1, 0, 1, 0, 1, 0], [0, 0, 0, 0, 0, 0, 0], [0, 1, 0, 1, 0, 1, 0], [0, 0, 0, 0, 0, 0, 0]]

1 Ответ

0 голосов
/ 07 мая 2018

Проблема в вашей функции base_maze, где вы сначала создаете два типа строк:

zero_row = []                                   #initialise a row of 0s
for i in range(num_columns):
    zero_row.append(0)

norm_row = []                                   #initialise a row of
for i in range(num_columns // 2):               #alternating 0s and 1s
    norm_row.extend([0,1])
norm_row.append(0)

Пока все нормально и работает, как и ожидалось, однако, когда вы строите лабиринт оттуда

for i in range(num_rows  // 2):                 # and normal rows)
    maze.append(zero_row)
    maze.append(norm_row)
maze.append(zero_row)

Вы заполняете список лабиринтов несколькими экземплярами одного и того же списка. Это означает, что если вы измените строку 0 лабиринта, строки 2 и 4 также будут затронуты. Для иллюстрации:

>>> def print_maze(maze):
...     print('\n'.join(' '.join(str(x) for x in row) for row in maze))
... 
>>> print_maze(maze)
0 0 0 0 0
0 1 0 1 0
0 0 0 0 0
0 1 0 1 0
0 0 0 0 0
>>> maze[0][0] = 3
>>> print_maze(maze)
3 0 0 0 0
0 1 0 1 0
3 0 0 0 0
0 1 0 1 0
3 0 0 0 0

Обратите внимание, что строки 0, 2 и 4 все изменились. Это связано с тем, что maze[0] - это тот же экземпляр zero_row, что и maze[2] и maze[4].

Вместо этого, когда вы создаете лабиринт, вы хотите использовать копию списков строк. Это легко сделать в Python, используя следующие обозначения нарезки

for i in range(num_rows  // 2):
    maze.append(zero_row[:]) # note the [:] syntax for copying a list
    maze.append(norm_row[:])
maze.append(zero_row[:])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...