Warning - This site is moving to https://getthecodingbug.anvil.app
Topics covered
​ Draw a grid of cells
Conway's Game of Life
Python version of Life
Draw a grid of cells
Using Pygame we will draw a grid of cells on the screen.
Create a new file called: 'drawCells.py' and copy these lines:
# drawCells.py - Draws a grid of cells
import pygame # Provides what we need to make a game
import random # Can generate random numbers
# Define dimensions of grid
DISPLAY_WIDTH = 640
DISPLAY_HEIGHT = 480
HALF_DISPLAY_WIDTH = DISPLAY_WIDTH / 2
HALF_DISPLAY_HEIGHT = DISPLAY_HEIGHT / 2
displaySize = (DISPLAY_WIDTH, DISPLAY_HEIGHT)
# Define size and number of cells
SIZE = 16
XCELLS = int(DISPLAY_WIDTH/SIZE)
YCELLS = int(DISPLAY_HEIGHT/SIZE)
# Create a list of colours
colours = []
colours.append((255, 255, 255))
colours.append(( 0, 0, 0))
WHITE = 0
BLACK = 1
# Constants for Left and Right Mouse button events
LEFT = 1
RIGHT = 3
# Create a list for cells in the grid
grid = [[WHITE for y in range(YCELLS)] for x in range(XCELLS)]
# Define a function to initialise all the cells
def initGrid(grid, c):
for y in range(YCELLS):
for x in range(XCELLS):
grid[x][y] = c
# Define a function to draw a square of colour(c) at coordinates, x and y
def drawCell(x, y, c):
pygame.draw.rect(screen, colours[c], pygame.Rect(x * SIZE, y * SIZE, SIZE-1, SIZE-1))
# Define a function to update cells on screen from grid
def update():
for y in range(YCELLS):
for x in range(XCELLS):
c = grid[x][y]
drawCell(x, y, c)
# Initialise pygame
pygame.init()
# Set the window title
pygame.display.set_caption("Draw a grid of cells")
# Create the window
screen = pygame.display.set_mode(displaySize)
# Blank screen
screen.fill(BLACK)
# Initialise the generations
initGrid(grid, WHITE)
# Update the full display surface to the screen
pygame.display.flip()
# Create a clock to manage time
clock = pygame.time.Clock()
# Initialise variables
done = False
drawingON = False
drawColour = WHITE
# Runs the game loop
while not done:
# The code here runs when every frame is drawn
# Get any events that have occurred, like close button(X) clicked
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
# handle Mouse
if event.type == pygame.MOUSEBUTTONDOWN:
drawingON = True
if event.button == LEFT:
drawColour = BLACK
elif event.button == RIGHT:
drawColour = WHITE
if event.type == pygame.MOUSEBUTTONUP:
drawingON = False
# Check for q key
if event.type == pygame.KEYUP:
if event.key == pygame.K_q:
done = True
# Check for drawingON
if drawingON:
pos = pygame.mouse.get_pos()
x = int(pos[0] / SIZE)
y = int(pos[1] / SIZE)
grid[x][y] = drawColour
# Update and draw
update()
# Update the full display surface to the screen
pygame.display.flip()
# Limit the game to 30 frames per second
clock.tick(60)
print('Quitting')
pygame.quit()
Running the program will create a grid of boxes which can be fill-in or cleared using the mouse.
When pressing the left-mouse button, a square is filled-in and pressing the right-mouse button, the square is cleared back to white. Holding the mouse button down fills in squares along the route, like drawing in a paint program.
You can change the size of the cells, by changing the variable: SIZE = 16. Try values like 32, 16, 8, 4 or 2.
You can also create different colours by adding lines after: colours.append(( 0, 0, 0))
To add the colour red, for example, insert this line:
colours.append((255, 0, 0))
Then add this line:
RED = 2
after: BLACK = 1
Conway's Game of Life
The Game of Life, also known simply as Life, is a cellular automaton devised by the British mathematician John Horton Conway in 1970. See here for more information: https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life
Python version of Life
Create a new file called: 'gameOfLife.py' and copy these lines:
# gameOfLife.py - Conway's Game of Life
# Rules
# Every cell interacts with its eight neighbours,
# which are the cells that are horizontally, vertically, or diagonally adjacent.
# At each step in time, the following transitions occur:
# 1. Any live cell with fewer than two live neighbours dies, as if caused by under population.
# 2. Any live cell with two or three live neighbours lives on to the next generation.
# 3. Any live cell with more than three live neighbours dies, as if by overpopulation.
# 4. Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.
# We will use colours to define the state of a cell
# WHITE means a Dead cell
# BLACK means a Live Cell
import pygame # Provides what we need to make a game
import random # Can generate random numbers
# Define dimensions of grid
DISPLAY_WIDTH = 640
DISPLAY_HEIGHT = 480
HALF_DISPLAY_WIDTH = DISPLAY_WIDTH / 2
HALF_DISPLAY_HEIGHT = DISPLAY_HEIGHT / 2
displaySize = (DISPLAY_WIDTH, DISPLAY_HEIGHT)
# Define size and number of cells
SIZE = 16
XCELLS = int(DISPLAY_WIDTH/SIZE)
YCELLS = int(DISPLAY_HEIGHT/SIZE)
# Create a list of colours
colours = []
colours.append((255, 255, 255))
colours.append(( 0, 0, 0))
WHITE = 0
BLACK = 1
# Create 2 lists, one for each generation of cells
current_generation = [[WHITE for y in range(YCELLS)] for x in range(XCELLS)]
next_generation = [[WHITE for y in range(YCELLS)] for x in range(XCELLS)]
# Define a function to initialise all the cells
def initGeneration(generation, c):
for y in range(YCELLS):
for x in range(XCELLS):
generation[x][y] = c
# Define a function to draw a square of colour(c) at coordinates, x and y
def drawCell(x, y, c):
pygame.draw.rect(screen, colours[c], pygame.Rect(x * SIZE, y * SIZE, SIZE-1, SIZE-1))
# Define a function to update cells on screen from next_generation array
def update():
global current_generation
for y in range(YCELLS):
for x in range(XCELLS):
c = next_generation[x][y]
drawCell(x, y, c)
# Update current_generation
current_generation = list(next_generation)
# Create a Live cell
def createLiveCell(x,y):
global next_generation
next_generation[x][y] = BLACK
# Kill a Live cell
def killLiveCell(x,y):
global next_generation
next_generation[x][y] = WHITE
# Function to check neighbour cell
def checkNeighbour(x, y):
# Ignore cell off the edge of the grid
if (x < 0) or (y < 0): return 0
if (x >= XCELLS) or (y >= YCELLS): return 0
# Check if cell is live
if current_generation[x][y] == BLACK:
return 1
else:
return 0
# Define a function to count neigbouring 8 cells if live
def countCellNeighbours(x,y):
n = 0
n += checkNeighbour(x-1, y-1)
n += checkNeighbour(x-1, y)
n += checkNeighbour(x-1, y+1)
n += checkNeighbour(x, y-1)
n += checkNeighbour(x, y+1)
n += checkNeighbour(x+1, y-1)
n += checkNeighbour(x+1, y)
n += checkNeighbour(x+1, y+1)
return(n)
# Define a function to breed the next generation of cells
def breedNextGeneration():
global next_generation
for y in range(YCELLS):
for x in range(XCELLS):
# If cell is live, count neighbouring live cells
n = countCellNeighbours(x,y)
c = current_generation[x][y]
# If cell is live check rules 1, 2 and 3
if c == BLACK:
if (n < 2) or (n > 3):
# Cell dies (rules 1 and 3)
next_generation[x][y] = WHITE
else:
# Cell lives on (rule 2)
next_generation[x][y] = BLACK
else:
if (n == 3):
# Cell is reborn (rule 4)
next_generation[x][y] = BLACK
# Initialise pygame
pygame.init()
# Set the window title
pygame.display.set_caption("Conway's Game of Life")
# Create the window
screen = pygame.display.set_mode(displaySize)
# Blank screen
screen.fill(BLACK)
# Initialise the generations
initGeneration(current_generation, WHITE)
# Update the full display surface to the screen
pygame.display.flip()
# Create a clock to manage time
clock = pygame.time.Clock()
# Initialise variables
done = False
breedCells = False
# Runs the game loop
while not done:
# The code here runs when every frame is drawn
# Get any events that have occurred, like close button(X) clicked
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
# handle Mouse
if event.type == pygame.MOUSEBUTTONDOWN:
pos = pygame.mouse.get_pos()
x = int(pos[0] / SIZE)
y = int(pos[1] / SIZE)
if next_generation[x][y] == WHITE:
createLiveCell(x,y)
else:
killLiveCell(x,y)
# Check for q, g, s or w keys
if event.type == pygame.KEYUP:
if event.key == pygame.K_q:
done = True
elif event.key == pygame.K_SPACE:
breedNextGeneration()
elif event.key == pygame.K_g:
breedCells = True
elif event.key == pygame.K_s:
breedCells = False
elif event.key == pygame.K_w:
breedCells = False
initGeneration(next_generation, WHITE)
if breedCells:
breedNextGeneration()
# Update and draw
update()
# Update the full display surface to the screen
pygame.display.flip()
# Limit the game to 30 frames per second
clock.tick(60)
print('Quitting')
pygame.quit()
When running the program, it will create a grid of white cells like before.
Create a few cells by clicking the mouse a few times on different but neighbouring cells.
The press the 'space-bar' to breed one generation of cells.
Keep pressing the 'space-bar' and notice how the cells evolve.
When you are happy that life will continue to exist, press the 'g' key to start breeding automatically, according the Conway's simple 4 rules.
Press 's' to stop the breeding, or press 'w' to wipe the grid clear so that you can start again.
Finally press 'q' to quit.
There is a lot more you can do with this. You could change the rules, example or add new rules.
You could also look up Langton's Ant, in Wikipedia, and see if you can code that in Python.