0

Here's the full code. I've left out few unnecessary things

import random
import pygame

FPS = 1
WIDTH, HEIGHT = 400, 400
RESOLUTION = 40

GRAY = (200, 200, 200)
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
WIN = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Game of Life")

def draw_grid(win, cols, rows):
for i in range(cols):
    for j in range(rows):
        x = i * RESOLUTION
        y = j * RESOLUTION
        pygame.draw.rect(win, GRAY, (x, y, RESOLUTION, RESOLUTION), 1)

def make_2d_array(cols, rows):
    arr = []
    for i in range(cols):
        arr.append([])
        for j in range(rows):
            arr[i].append(0)

    return arr

def count_neighbours(grid, x, y):
    neighbourCount = 0
    for i in range(-1, 2):
        for j in range(-1, 2):
            neighbourCount += grid[x + i][y + j]

    return neighbourCount

def draw_squares(win, grid, cols, rows):
    #nextA = make_2d_array(cols, rows)
    nextA = grid

    for i in range(len(grid)):
        for j in range(len(grid[i])):
            x = i * RESOLUTION
            y = j * RESOLUTION
            if grid[i][j] == 1:
                pygame.draw.rect(win, WHITE, (x, y, RESOLUTION, RESOLUTION))
            elif grid[i][j] == 0:
                pygame.draw.rect(win, BLACK, (x, y, RESOLUTION, RESOLUTION))

    for i in range(cols):
        for j in range(rows):

            if i == 0 or i == cols-1 or j == 0 or j == rows-1:
                nextA[i][j] = grid[i][j]
            else:
                state = grid[i][j]
                neighbours = count_neighbours(grid, i, j)

                if state == 0 and neighbours == 3:
                    nextA[i][j] = 1
                elif state == 1 and (neighbours < 2 or neighbours > 3):
                    nextA[i][j] = 0
                else:
                    nextA[i][j] = state
    grid = nextA

def main():
    run = True
    clock = pygame.time.Clock()
    
    cols = int(WIDTH / RESOLUTION)
    rows = int(HEIGHT / RESOLUTION)

    grid = make_2d_array(cols, rows)

    """for i in range(cols):
        for j in range(rows):
            grid[i][j] = random.randint(0, 1)"""
    #glider test

    grid = [[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, 1, 0, 1, 0, 0, 0, 0],
            [0, 0, 0, 0, 1, 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, 1, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]
    while run:
        clock.tick(FPS)

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

        draw_squares(WIN, grid, cols, rows)
        draw_grid(WIN, cols, rows)
        pygame.display.update()

    pygame.quit()


main()

I was following along with a tutorial that was written in Java or JavaScript but the rules are the same and should work but they don't. The rules simplified should be this:

            if state == 0 and neighbours == 3:
                nextA[i][j] = 1
            elif state == 1 and (neighbours < 2 or neighbours > 3):
                nextA[i][j] = 0
            else:
                nextA[i][j] = state

but when I run the code the first if-statement works I'm pretty sure (it's kinda hard to understand the program behaves weirdly).

khelwood
  • 55,782
  • 14
  • 81
  • 108
giji676
  • 55
  • 1
  • 7

1 Answers1

1

The implementation of the rules is correct, but in Conway's Game of Life you have to create a new and empty grid every turn. The fields in the new grid must be determined depending on the fields in the current grid and the evolution rules.

Create a new and empty grid in draw_squares, but return the new grid form the function:

def draw_squares(win, grid, cols, rows):

    # nextA = grid                        # <--- DELETE
    nextA = make_2d_array(cols, rows)     # <--- ADD

    # [...]

    return nextA                          # <-- return the new grid

Make the new grid the current grid by assigning the new grid returned by draw_squares to grid:

grid = draw_squares(WIN, grid, cols, rows)

Additionally the computation of the neighbors is wrong. A field is not a neighbor of itself:

def count_neighbours(grid, x, y):
    neighbourCount = 0
    for i in range(-1, 2):
        for j in range(-1, 2):
            if i != 0 or j != 0:
                neighbourCount += grid[x + i][y + j]

    return neighbourCount
Rabbid76
  • 202,892
  • 27
  • 131
  • 174
  • ok so if i understand correctly i uncommented nextA = make_2d_array(cols, rows) added return nextA at the end of draw_squares and when i call the draw_squares i stored it into variable it didn't work fully but im getting better behaviour – giji676 Jan 07 '21 at 14:51
  • accidentaly pressed enter didnt finish the comment fully srry – giji676 Jan 07 '21 at 14:53
  • yes thats exactly what i did but when i try to run the glider it doesnt work – giji676 Jan 07 '21 at 14:55
  • @giji676 A field is not a neighbor of itself. See the answer. – Rabbid76 Jan 07 '21 at 15:00
  • 1
    oh thank you so much, i did a few versions of the game trying to fix the issue and forgot to add that in this version tysm – giji676 Jan 07 '21 at 15:03