1
votes

I have a piece of code that is supposed to place 1000 squares on screen, none overlapping.

But when I run it, I just get a bunch of squares where some of them ARE overlapping, any idea where I went wrong?

import time, pygame, ctypes, random

class Block(pygame.sprite.Sprite):
    def __init__(self, color, width, height):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.Surface([width, height])
        self.image.fill(color)
        self.rect = self.image.get_rect()

white = (255,255,255)
black = (0, 0, 0)
user32 = ctypes.windll.user32
sw = user32.GetSystemMetrics(0)
sh = user32.GetSystemMetrics(1)

Bloqs = {}
#Bloq atributes: Position (upper left), Size, Color, Genetics

pygame.init()
all_sprites_list = pygame.sprite.Group()

def Collision(bloq):
    global all_sprites_list
    hit = pygame.sprite.spritecollide(bloq, all_sprites_list, True)
    if len(hit) == 0:
        return False
    if len(hit) > 0:
        return True

def InitializeSim():
    global Bloqs
    global white
    global black
    global sw
    global sh
    global all_sprites_list

    size = sw, sh
    screen = pygame.display.set_mode(size, pygame.FULLSCREEN )
    screen.fill(white)
    count = 0
    while count < 1000:
        size = 10
        pos = random.seed()
        posx = random.randint(0, sw-size)
        posy = random.randint(0, sh-size)
        #pygame.draw.rect(screen, color, (x,y,width,height), thickness)
        CurrentBloq = "bloq" + str(count)
        Bloqs[CurrentBloq]={}
        Bloqs[CurrentBloq]["position"] = (sw, sh)
        bloq = Block(black, size, size)
        bloq.rect.x = posx
        bloq.rect.y = posy
        Bloqs[CurrentBloq]["sprite"] = bloq
        all_sprites_list.add(bloq)
        all_sprites_list.draw(screen)
        pygame.display.update()
        while Collision(bloq) == True:
            all_sprites_list.remove(bloq)
            posx = random.randint(0, sw-size)
            posy = random.randint(0, sh-size) 
            bloq.rect.x = posx
            bloq.rect.y = posy
            all_sprites_list.add(bloq)
            all_sprites_list.draw(screen)
            pygame.display.update()
        count += 1

InitializeSim()
time.sleep(5)
pygame.quit()
2

2 Answers

1
votes

Your code seems pretty complex for what you are trying to do...

approach it as a whole however feels natural for you, but when generating the blocks, I would follow something more along the lines of:

for i in range(numberofblocksyouwant):

    while true:
        create a block at a random x,y pos
        if block collides with any existing blocks:
            remove the block you just created
        else: 
            break

For every block you want, this approach would keep recreating each block until it picks a random x,y that does not end up colliding with any other blocks.

However, if your blocks fill up the screen and make doing this impossible, the nested while loop will never end.

Hope that helps, let me know if that doesn't make sense.

1
votes

To build upon Max's answer:

You would probably want a system to abort if there are to many iterations without success.

I would write it:

for i in range(numberofblocksyouwant):

while true:
    numberofattempts = 0
    create a block at a random x,y pos
    if block collides with any existing blocks:
        remove the block you just created
        numberofattempts += 1
        if numberofattempts > 1000:
           return "took too many attempts"
    else:
       break