Slein Buyt
Slein Buyt

Reputation: 3

Can't figure out why two arrays are copy of each other

So I'm learning python and trying to code Conway's game of life : (link)

I created a grid, on which you can click to select tiles, and a 2D array that contain the value 1 if the tiles is active, 0 if it's not.

Then, i need to calculate the number of neighboors of each tile. To do that I created a function (voisins_calc) and an other 2D array containing the number of neighboors for each tile.

The problem is : the 2D arrays 'state' and 'voisins' are copys of each other, and I really don't know why ! I think state is copying the value of voisins but I can't see where.

Here's the code ( I put the entire code despite the rules, since I don't know where it's going wrong, sorry for that)

import pygame
pygame.init()

screen_height = screen_width = 700
win = pygame.display.set_mode((screen_height, screen_width))
run = True

cols = rows = 2
state = []
voisins = []

def state_init():
    line = []
    line_transi = []
    for col in range (cols):
        for row in range (rows):
            line.append(0)
        line_transi = line.copy()
        state.append(line_transi)
        voisins.append(line_transi)
        line.clear()
    return (state)

def voisins_calc (x, y):
    voisin = 0
    for i in range (-1, 2, 1):
        for j in range (-1, 2, 1):
            if state[(y + rows + i) % rows][(x + cols + j) % cols] == 1:
                voisin += 1
    if state[x][y] == 1 :
        voisin -= 1
    return (voisin)


state_init()   

while run : 
    print(state, voisins)
    pygame.time.delay(100)

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

    if pygame.mouse.get_pressed()[0]:
        state[round(pygame.mouse.get_pos()[1] // (screen_height / rows))] 
   [round(pygame.mouse.get_pos()[0] // (screen_width / cols))] = 1
    if pygame.mouse.get_pressed()[1]:
        state[round(pygame.mouse.get_pos()[1] // (screen_height / rows))] 
   [round(pygame.mouse.get_pos()[0] // (screen_width / cols))] = 0

    keys = pygame.key.get_pressed()

    if keys[pygame.K_SPACE]:
        for col in range (cols):
            for row in range (rows):
                voisins[row][col] = voisins_calc(row, col)

    win.fill((249, 203, 156))

    for col in range (cols):
        for row in range (rows):
            if state[col][row] == 1 :
                pygame.draw.rect(win, (75, 75, 75), (row * (screen_width / 
rows), col * (screen_height / cols), (screen_width / cols), (screen_height 
/ rows)), 0)

    for row in range (rows) : 
        pygame.draw.line(win, (0, 0, 0),(row * screen_height / rows, 0), 
(row * screen_height / rows, screen_width), 1)
    for col in range (cols):
        pygame.draw.line(win, (0, 0, 0),(0, col * screen_width / cols), 
(screen_width, col * screen_width / cols), 1)
    print(state, voisins)
    pygame.display.update()

pygame.quit()

Upvotes: 0

Views: 37

Answers (2)

Carcigenicate
Carcigenicate

Reputation: 45750

In state_init, you add the same copy to each state and voisins:

state.append(line_transi)  # These are the same lists
voisins.append(line_transi)

You need to add a copy to voisins if you want them to be separate.

I'll note though, you're making this a lot more complicated than it needs to be. Just create a helper to create a grid, then call it twice:

def create_grid(width, height):
    # 2D list comprehension to create nested list
    return [[0 for _ in range(width)] for _ in range(height)]

state = create_grid(cols, rows)
voisins = create_grid(cols, rows)

Upvotes: 2

MCI
MCI

Reputation: 922

line_transi = line.copy()
state.append(line_transi)
voisins.append(line_transi)

Here you append the same array line_transi to both state and voisins. An alternative,

state.append(line.copy())
voisins.append(line.copy())

Upvotes: 1

Related Questions