Reputation: 93
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)
Upvotes: 1
Views: 472
Reputation: 2500
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.
Upvotes: 1
Reputation: 142661
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()
Upvotes: 1