只要不满足失败条件,重复功能

时间:2019-06-29 09:45:13

标签: python python-3.x multidimensional-array do-while

我正在创建一个利用程序创建的地牢图的python roguelike。我决定使用pythons的列表来实现这一点。我创建了一个2d列表(矩阵)用作地图,并使用0表示空白。为了在地牢中创建“房间”,我使用了随机生成的变量来确定房间右上角的随机行和列,并使用for循环并遍历随机数的行和行,将0替换为1(以表示房间)。列:

示例网格事先

00000000000000
00000000000000
00000000000000
00000000000000
00000000000000
00000000000000

创建并插入房间后的示例网格:

00000000000000  or  00000000000000 etc
01111000000000      00000111111000
01111000000000      00000111111000
01111000000000      00000000000000
00000000000000      00000000000000
00000000000000      00000000000000 

具有创建网格,创建和插入房间以及打印网格的功能的代码:

import random

rand_row = random.randint(0,25)
rand_column = random.randint(0,25)
room_height = random.randint(7,15)
room_length = random.randint(7,15)

def create_grid():
    global grid
    grid = [[0 for column in range (50)] for row in range(50)]
    create_room()

def create_room():
    global grid
    print (f"Room generated is of length {room_length} and height {room_height}")
    print (f"Room placed randomly in row {rand_row} and column {rand_column}")
    print (" ")

    if room_height > 0:
        for point in grid[rand_row]:
            for each_number in range(room_length):
                for increment in range(room_height):
                    grid[rand_row+increment][rand_column+each_number] = 1


def print_grid():
    global grid
    for row in grid:
        print(" ".join(map(str,row)))

create_grid()
print_grid()

我不知道该怎么做,就是要生成多个房间,同时确保它们之间没有重叠。我试图使一个检查子例程返回一个布尔值,该布尔值取决于房间大小和位置的随机生成的值是否可以工作(如果与另一个房间重叠,则不能工作):

def check_if_space_taken():
    global space_is_taken
    global grid
    for each_row in range(rand_row,room_height+rand_row):
        if any(1 in each_row for each_row in grid):
            space_is_taken = True
        else:
            space_is_taken = False

但是,我不知道如何利用它,我甚至不确定它是否有效。我还创建了一个更改所有房间值的函数:

def change_room_params():
    cfg.first_row = random.randint(0,50)
    cfg.first_column  = random.randint(0,50)
    cfg.temp_room_height = random.randint(5,20)
    cfg.temp_room_length = random.randint(5,20)

但是我知道,如果随机数继续给出不起作用的值,则检查过程可能会花费很长时间。

总而言之,我如何为新房间创建新参数并检查房间之间是否有重叠:因此创建新值并在有重叠的情况下重复该过程,或者在没有重叠的情况下创建该房间,然后重复该过程。进行处理,直到绝对没有空间容纳更多房间为止。

非常感谢您的帮助。香港专业教育学院张贴这个问题之前,但删除并重新做了更多细节。一般而言,我对python或编程的经验不是很丰富,因此非常感谢提高我的任务效率的建议。

1 个答案:

答案 0 :(得分:0)

一种改进是使用numpy arrays而不是python列表。尤其是当您有巨大的地图时。

然后,您可以使用skimage draw module绘制多边形或矩形。要检查房间是否拦截,您可以检查新房间的任何点处数组中是否已有1。此检查不应花费很长时间。尤其是只有一次时。为了避免无限循环。您可以设置较高的最大迭代次数。而且,如果您没有足够的房间,只需将阵列清零并重做该过程即可。

我创建了一个应该起作用的代码。如果您有任何问题,请随时在评论中提问。

没有numpy和skimage的方法

def insert_room(data, row, col) -> bool:
    if row + ROOM_HEIGHT > MAP_HEIGHT or col + ROOM_LENGTH > MAP_WIDTH or row < 0 or col < 0:
        return False
    # This method assumes that all rooms are equal in size
    if (data[row][col] == 1 or
            data[row + ROOM_HEIGHT - 1][col] == 1 or
            data[row][col + ROOM_LENGTH - 1] == 1 or
            data[row + ROOM_HEIGHT - 1][col + ROOM_LENGTH - 1] == 1):
        return False
    for r in range(row, row + ROOM_HEIGHT):
        for c in range(col, col + ROOM_LENGTH):
            data[r][c] = 1
    return True

允许所有房间大小

def insert_room(data, row, col) -> bool:
    if row + ROOM_HEIGHT > MAP_HEIGHT or col + ROOM_LENGTH > MAP_WIDTH or row < 0 or col < 0:
        return False
    # Can room be added
    for r in range(row, ROOM_HEIGHT):
        if any(data[r][col:col+ROOM_LENGTH]):
            return False
    # Add room
    for r in range(row, row + ROOM_HEIGHT):
        for c in range(col, col + ROOM_LENGTH):
            data[r][c] = 1
    return True

具有numpy和skimage的方法

import numpy as np
import random
import skimage.draw

MAP_WIDTH = 10
MAP_HEIGHT = 10

ROOM_LENGTH = 3
ROOM_HEIGHT = 3

NUM_ROOMS = 5


def create_map():
    # These values define how long you gonna to try to create a map
    outer_max_iteration = 10
    max_iteration = 1000

    outer_iteration = 0
    iteration = 0

    created_rooms = 0

    data = np.zeros((MAP_WIDTH, MAP_HEIGHT))
    while created_rooms < NUM_ROOMS and outer_iteration < outer_max_iteration:
        data = np.zeros((MAP_WIDTH, MAP_HEIGHT))
        while created_rooms < NUM_ROOMS and iteration < max_iteration:
            col = random.randint(0, MAP_WIDTH - ROOM_LENGTH)
            row = random.randint(0, MAP_HEIGHT - ROOM_HEIGHT)
            inserted = insert_room(data, col, row)
            created_rooms += inserted

            iteration += 1
        outer_iteration += 1
    if created_rooms < NUM_ROOMS:
        print("ERROR: Map cannot contain so many rooms!")
    print(data)
    return data


def insert_room(data, row, col) -> bool:
    # check bounds
    if row + ROOM_HEIGHT > MAP_HEIGHT or col + ROOM_LENGTH > MAP_WIDTH or row < 0 or col < 0:
        return False

    #: The rows of the polygon
    r = np.array([row, row, row + ROOM_HEIGHT, row + ROOM_HEIGHT])
    #: The columns of the polygon
    c = np.array([col, col + ROOM_LENGTH, col + ROOM_LENGTH, col])

    # create data where room should be created
    rr, cc = skimage.draw.polygon(r, c)

    #: check if room overlap with existing
    if not any(data[rr, cc]):
        data[rr, cc] = 1
        return True
    return False

示例输出:

[[0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [1. 1. 1. 0. 0. 0. 1. 1. 1. 0.]
 [1. 1. 1. 1. 1. 1. 1. 1. 1. 0.]
 [1. 1. 1. 1. 1. 1. 1. 1. 1. 0.]
 [0. 0. 0. 1. 1. 1. 1. 1. 1. 0.]
 [0. 0. 0. 0. 0. 0. 1. 1. 1. 0.]
 [0. 1. 1. 1. 0. 0. 1. 1. 1. 0.]
 [0. 1. 1. 1. 0. 0. 0. 0. 0. 0.]
 [0. 1. 1. 1. 0. 0. 0. 0. 0. 0.]]