随机化列表列表而不重叠

Randomizing list of lists without overlap

我正在制作一个函数,为游戏战舰随机化一个游戏板(由十个列表中的十个列表表示)。我的功能目前所做的是在代表船只的棋盘上随机放置数字。我的功能还确保船只不会绕着板的边缘出现并出现在另一侧,以及随机生成船只的方向。然而,我的功能未能实现的是确保“船只”不会相互重叠。我一直难以想出解决方案,但我确信它非常简单。有什么办法可以实现我的目标吗?

import random
l = [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
     [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
     [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
     [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
     [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
     [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
     [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
     [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
     [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
     [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]

for a in range(1, 5):
    p = random.randrange(0, 10, 1)
    o = random.randrange(0, 10, 1)
    #the p and o variables determine the coordinates of the starting point
    r = random.randrange(1, 3)
    #the r variable randomizes orientation of the ship
    if r == 1:
        for n in range(1, 7 - a):
            #the function uses the length of the ship to determine whether or not 
            #the ship will go off the end of the board
            if o < 6 - a:
                l[p][(6 - a) - n] = 6 - a
            else:
                l[p][o-n] = 6 - a
    else:
        for e in range(1, 7 - a):

            if p < 6-a:
                l[(6-a) - e][o] = 6-a
            else:
                l[p - e][o] = 6-a
for v in range(0, len(l)):
    print(l[v])

输出示例:

[0, 3, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 3, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 3, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 4, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 4, 0, 0, 5, 5, 5, 5, 5, 0]
[0, 4, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 4, 0, 0, 0, 0, 0, 0, 2, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 2, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

重叠输出(五艘船被三艘船覆盖):

[0, 0, 0, 0, 5, 5, 5, 5, 3, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 3, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 3, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[2, 2, 0, 0, 0, 0, 0, 0, 0, 0]
[4, 4, 4, 4, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

冒着使事情过于复杂的风险,我建议采用面向对象的方法。可以修改你的方法,但我发现它很快就会变得混乱。

place 函数中,我们 assemble 一个 locations 的列表来放置以制造飞船。然后我们检查是否有任何船只已经位于那里 grid[y][x] != 0。如果是这样,我们需要重新generate位置和旋转的随机值,然后我们可以再次尝试place

import random

GRID_WIDTH, GRID_HEIGHT = 10, 10  # constants representing width and height of the board
grid = [[0 for _ in range(GRID_WIDTH)] for _ in range(GRID_HEIGHT)]  # generate a 10x10 grid of 0's


class Ship:
    def __init__(self, length):
        self.length = length
        self.x, self.y, self.horizontal = None, None, None
        self.generate()

    def generate(self):  # randomize position and rotation
        self.x = random.randint(0, GRID_WIDTH-self.length)
        self.y = random.randint(0, GRID_HEIGHT-self.length)
        self.horizontal = random.choice([True, False])
        self.place()

    def place(self):  # place ship on the grid
        locations = []
        if self.horizontal:
            for x in range(self.x, self.x+self.length):
                locations.append((x, self.y))
        else:  # if vertical
            for y in range(self.y, self.y+self.length):
                locations.append((self.x, y))
        for x, y in locations:
            if grid[y][x] != 0:  # if occupied, regenerate whole ship
                self.generate()
                return
        for x, y in locations:  # actually place ship now
            grid[y][x] = self.length


ships = []
for ship_length in range(2, 6):
    ships.append(Ship(ship_length))

for row in grid:  # print the board
    print(row)

# for row in grid:  # print the board without 0's
#     print(str(row).replace('0', ' '))

如果您对代码有任何疑问,请告诉我。