Search code examples
pythonarrayspython-3.xpygameconways-game-of-life

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)

Solution

  • 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()
            self.screen = pygame.display.set_mode((WINDOWSIZE, WINDOWSIZE))
            pygame.display.set_caption('Game of Life')
    
            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()