radicz radicz - 27 days ago 15
Python Question

Conway's Game of Life - rules

below is my code for Conway's game of life. I am currently struggling with incorrect functionality - the cells are still reproducing instead of extinction or point of convergence. I think that something went wrong in rules function (I think, that particular rules are ok?), but I am unable to figure it out. If you have a clue what went wrong, I would appreciate your help. Thanks

import pygame
import sys
import random
from pygame.locals import *

FPS = 10
fpsClock = pygame.time.Clock()

WINDOWSIZE = 500
CELLSIZE = 5
assert WINDOWSIZE % CELLSIZE == 0, "win size must be a multiple of cell"


class Board():

def __init__(self):

pygame.init()
pygame.display.set_caption('Game of Life')
self.DISPLAYSURF = pygame.display.set_mode((WINDOWSIZE, WINDOWSIZE))
self.grid = [[0] * (WINDOWSIZE // CELLSIZE) for i in range(WINDOWSIZE // CELLSIZE)]

def draw(self):
i = 0
j = 0

for x in range(0, WINDOWSIZE, CELLSIZE):
for y in range(0, WINDOWSIZE, CELLSIZE):

if self.grid[i][j] == 0:
pygame.draw.rect(
self.DISPLAYSURF, (20, 120, 20), Rect((x, y), (CELLSIZE, CELLSIZE)))

else:
pygame.draw.rect(
self.DISPLAYSURF, (255, 255, 255), Rect((x, y), (CELLSIZE, CELLSIZE)))

if j == (WINDOWSIZE // CELLSIZE) - 1:
j = 0

else:
j = j + 1

i = i + 1

def randomize(self):
for i in range(CELLSIZE, (WINDOWSIZE // CELLSIZE) - CELLSIZE):
for j in range(CELLSIZE, (WINDOWSIZE // CELLSIZE) - CELLSIZE):

if random.randint(0, 100) < 15:
self.grid[i][j] = 1


def rules(self):
for i in range(CELLSIZE, (WINDOWSIZE // CELLSIZE) - CELLSIZE):
for j in range(CELLSIZE, (WINDOWSIZE // CELLSIZE) - CELLSIZE):

neighbors = 0

if self.grid[i][j] == 0:
neighbors = self.grid[i + 1][j] + self.grid[i - 1][j] + self.grid[i][j + 1] + self.grid[i][j - 1] + self.grid[i - 1][j - 1] + self.grid[i + 1][j + 1] + self.grid[i + 1][j - 1] + self.grid[i - 1][j + 1]

if neighbors == 3:
self.grid[i][j] = 1
continue
else:
self.grid[i][j] = 0

if self.grid[i][j] == 1:
neighbors = self.grid[i + 1][j] + self.grid[i - 1][j] + self.grid[i][j + 1] + self.grid[i][j - 1] + self.grid[i - 1][j - 1] + self.grid[i + 1][j + 1] + self.grid[i + 1][j - 1] + self.grid[i - 1][j + 1]

if neighbors < 2:
self.grid[i][j] = 0

elif neighbors > 3:
self.grid[i][j] = 0

else:
self.grid[i][j] = 1


board = Board()
board.randomize()

while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()

board.rules()
board.draw()
pygame.display.update()
fpsClock.tick(FPS)

Answer

Your mistake - you change values in cells in grid when you still need oryginal values to calculate other cells. You can't change values in oryginal grid. You have to put new values in new new_grid and replace grids at the end.

import pygame
import sys
import random

# --- constanst ---

FPS = 10
WINDOWSIZE = 500
CELLSIZE = 5

assert WINDOWSIZE % CELLSIZE == 0, "win size must be a multiple of cell"

# --- classes ---

class Board():

    def __init__(self):
        pygame.init()
        pygame.display.set_caption('Game of Life')

        self.screen = pygame.display.set_mode((WINDOWSIZE, WINDOWSIZE))

        self.grid = [[0] * (WINDOWSIZE // CELLSIZE) for i in range(WINDOWSIZE // CELLSIZE)]

    def draw(self):

        for i, x in enumerate(range(0, WINDOWSIZE, CELLSIZE)):
            for j, y in enumerate(range(0, WINDOWSIZE, CELLSIZE)):

                if self.grid[i][j] == 0:
                    color = (20, 120, 20)
                else:
                    color = (255, 255, 255)

                pygame.draw.rect(self.screen, color, pygame.Rect((x, y), (CELLSIZE, CELLSIZE)))


    def randomize(self):

        for i in range(CELLSIZE, (WINDOWSIZE // CELLSIZE) - CELLSIZE):
            for j in range(CELLSIZE, (WINDOWSIZE // CELLSIZE) - CELLSIZE):
                if random.randint(0, 100) < 15:
                    self.grid[i][j] = 1


    def rules(self):
        # create new grid
        new_grid = [[0] * (WINDOWSIZE // CELLSIZE) for i in range(WINDOWSIZE // CELLSIZE)]

        # put results in new grid
        for i in range(CELLSIZE, (WINDOWSIZE // CELLSIZE) - CELLSIZE):
            for j in range(CELLSIZE, (WINDOWSIZE // CELLSIZE) - CELLSIZE):

                neighbors = self.grid[i + 1][j] + self.grid[i - 1][j] + self.grid[i][j + 1] + self.grid[i][j - 1] + self.grid[i - 1][j - 1] + self.grid[i + 1][j + 1] + self.grid[i + 1][j - 1] + self.grid[i - 1][j + 1]

                if self.grid[i][j] == 0:
                    if neighbors == 3:
                        new_grid[i][j] = 1
                    else:
                        new_grid[i][j] = 0
                elif self.grid[i][j] == 1:
                    if neighbors < 2:
                        new_grid[i][j] = 0
                    elif neighbors > 3:
                        new_grid[i][j] = 0
                    else:
                        new_grid[i][j] = 1

        # replace grid
        self.grid = new_grid

    def mainloop(self):
        fps_clock = pygame.time.Clock()

        while True:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    pygame.quit()
                    sys.exit()
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_ESCAPE:
                        pygame.quit()
                        sys.exit()

            self.rules()
            self.draw()
            pygame.display.update()

            fps_clock.tick(FPS)        

# --- main ---

board = Board()
board.randomize()
board.mainloop()