Conway's Game Of Life using Python?

Conway's Game of Life is a cellular automaton created by British mathematician John Conway in 1970. It simulates the evolution of a colony of biological organisms on a two-dimensional grid consisting of "living" and "dead" cells.

Rules of Conway's Game of Life

The game follows four simple rules that determine whether a cell lives or dies in the next generation ?

  • Overpopulation: A living cell dies if it has more than three living neighbors

  • Survival: A living cell survives if it has two or three living neighbors

  • Underpopulation: A living cell dies if it has fewer than two living neighbors

  • Reproduction: A dead cell becomes alive if it has exactly three living neighbors

2 neighbors - Survives 3 neighbors - Survives/Born 4+ neighbors - Dies Living cell Dying cell Dead cell

Implementation Steps

The implementation follows these key steps ?

  1. Initialize an empty universe (grid)
  2. Fill the universe with a random seed pattern
  3. Calculate each cell's survival based on neighbor count
  4. Apply rules simultaneously to all cells
  5. Repeat for desired number of generations

Installation

Install the required libraries using pip ?

pip install numpy matplotlib

Complete Implementation

Here's a complete implementation of Conway's Game of Life with visualization ?

import numpy as np
import matplotlib.pyplot as plt
import argparse
import time

class Board(object):
    def __init__(self, size, seed='Random'):
        if seed == 'Random':
            self.state = np.random.randint(2, size=size)
        self.engine = Engine(self)
        self.iteration = 0
    
    def animate(self):
        i = self.iteration
        im = None
        plt.title("Conway's Game of Life")
        while True:
            if i == 0:
                plt.ion()
                im = plt.imshow(self.state, vmin=0, vmax=2, cmap=plt.cm.gray)
            else:
                im.set_data(self.state)
            i += 1
            self.engine.applyRules()
            print('Life Cycle: {} Birth: {} Survive: {}'.format(
                i, self.engine.nBirth, self.engine.nSurvive))
            plt.pause(0.01)
            yield self

class Engine(object):
    def __init__(self, board):
        self.state = board.state
    
    def countNeighbors(self):
        state = self.state
        n = (state[0:-2,0:-2] + state[0:-2,1:-1] + state[0:-2,2:] +
             state[1:-1,0:-2] + state[1:-1,2:] + state[2:,0:-2] +
             state[2:,1:-1] + state[2:,2:])
        return n
    
    def applyRules(self):
        n = self.countNeighbors()
        state = self.state
        birth = (n == 3) & (state[1:-1,1:-1] == 0)
        survive = ((n == 2) | (n == 3)) & (state[1:-1,1:-1] == 1)
        state[...] = 0
        state[1:-1,1:-1][birth | survive] = 1
        nBirth = np.sum(birth)
        self.nBirth = nBirth
        nSurvive = np.sum(survive)
        self.nSurvive = nSurvive
        return state

def main():
    ap = argparse.ArgumentParser(add_help=False)
    ap.add_argument('-h', '--height', help='Board Height', default=256)
    ap.add_argument('-w', '--width', help='Board Width', default=256)
    args = vars(ap.parse_args())
    bHeight = int(args['height'])
    bWidth = int(args['width'])
    board = Board((bHeight, bWidth))
    for _ in board.animate():
        pass

if __name__ == '__main__':
    main()

Simple Example

Here's a simpler version to understand the core logic ?

import numpy as np

def count_neighbors(grid):
    """Count living neighbors for each cell"""
    neighbors = np.zeros_like(grid)
    rows, cols = grid.shape
    
    for i in range(rows):
        for j in range(cols):
            for di in [-1, 0, 1]:
                for dj in [-1, 0, 1]:
                    if di == 0 and dj == 0:
                        continue
                    ni, nj = (i + di) % rows, (j + dj) % cols
                    neighbors[i, j] += grid[ni, nj]
    return neighbors

def update_grid(grid):
    """Apply Conway's rules"""
    neighbors = count_neighbors(grid)
    new_grid = np.zeros_like(grid)
    
    # Apply the four rules
    for i in range(grid.shape[0]):
        for j in range(grid.shape[1]):
            if grid[i, j] == 1:  # Living cell
                if neighbors[i, j] in [2, 3]:
                    new_grid[i, j] = 1  # Survives
            else:  # Dead cell
                if neighbors[i, j] == 3:
                    new_grid[i, j] = 1  # Born
    
    return new_grid

# Example: Blinker pattern
grid = np.array([[0, 1, 0],
                 [0, 1, 0],
                 [0, 1, 0]])

print("Initial state:")
print(grid)

for generation in range(3):
    grid = update_grid(grid)
    print(f"\nGeneration {generation + 1}:")
    print(grid)
Initial state:
[[0 1 0]
 [0 1 0]
 [0 1 0]]

Generation 1:
[[0 0 0]
 [1 1 1]
 [0 0 0]]

Generation 2:
[[0 1 0]
 [0 1 0]
 [0 1 0]]

Generation 3:
[[0 0 0]
 [1 1 1]
 [0 0 0]]

Output

When running the complete implementation, you'll see console output showing the evolution ?

Life Cycle: 1 Birth: 7166 Survive: 10621
Life Cycle: 2 Birth: 7930 Survive: 8409
Life Cycle: 3 Birth: 7574 Survive: 8756
Life Cycle: 4 Birth: 7114 Survive: 8406
Life Cycle: 5 Birth: 7005 Survive: 8126
...

The graphical display will show an animated grid where black pixels represent living cells and white pixels represent dead cells. The patterns will continuously evolve, creating fascinating shapes like gliders, oscillators, and still lifes.

Conclusion

Conway's Game of Life demonstrates how simple rules can create complex, emergent behavior. The Python implementation uses NumPy for efficient array operations and matplotlib for visualization, making it easy to observe the beautiful patterns that emerge from the cellular automaton.

Updated on: 2026-03-25T05:35:49+05:30

755 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements