简体   繁体   中英

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)

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()

Do not modify the cells until you move to the next generation! Below is the simple algorithm you need to follow. You can look for the detailed implementation and video demo here .

  1. Create a grid which will represent your cells.
  2. A Cell can be dead or alive. So have two css classes, one for alive and one for dead.
  3. Figure out neighbours of a cell.
  4. Apply above rules and figure out if the cell will be alive or dead for the next generation.
  5. Store the cells which needs to be moved to next generation.
  6. Store the cells which will not survive or will die in next generation.
  7. Iterate over the list of cells moving to next generation, and mark them as alive by adding alive css class to them
  8. Iterate over the list of cells which will die in next generation and mark them as dead by adding dead css class to them.
  9. Run the steps from 3-8 all over again after a small time interval.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM