Skip to content

Instantly share code, notes, and snippets.

@philipnorton42
Last active November 29, 2021 19:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save philipnorton42/dfb332ce247e9d79e29626bae79651af to your computer and use it in GitHub Desktop.
Save philipnorton42/dfb332ce247e9d79e29626bae79651af to your computer and use it in GitHub Desktop.
Conway's Game Of Life With Tkinter In Python. See https://www.hashbangcode.com/article/conways-game-life-tkinter-python
'''
Conway's Game Of Life With Tkinter In Python
See https://www.hashbangcode.com/article/conways-game-life-tkinter-python for
a detailed breakdown of this code.
'''
import tkinter as tk
from tkinter import Canvas
import random, math
class game_of_life(tk.Tk):
def __init__(self, width_and_height = 400, resolution = 100):
super().__init__()
self.title("Game of life")
# Prevent the application window from being resized.
self.resizable(False, False)
# Set the height and width of the applciation.
self.width_and_height = width_and_height
self.resolution = resolution
self.size_factor = self.width_and_height / self.resolution
# Set up the size of the canvas.
self.geometry(str(self.width_and_height) + "x" + str(self.width_and_height))
# Create the canvas widget and add it to the Tkinter application window.
self.canvas = Canvas(self, width=self.width_and_height, height=self.width_and_height, bg='white')
self.canvas.pack()
# Set a click event on the canvas.
self.canvas.bind('<Button-1>', self.canvas_click_event)
self.canvas.bind('<Button1-Motion>', self.canvas_click_event)
# Set up an empty game grid.
self.grid = [[0 for x in range(self.resolution)] for x in range(self.resolution)]
# Fill the game grid with random data.
for x in range(0, self.resolution):
for y in range(0, self.resolution):
self.grid[x][y] = random.randint(0, 1)
# Genearte the game board.
self.generate_board()
# Start the timer.
self.after(100, self.update_board)
def update_board(self):
# Clear the canvas.
self.canvas.delete("all")
# Run the next generation and update the game grid.
self.grid = self.run_generation()
# Generate the game board with the current population.
self.generate_board()
# Set the next tick in the timer.
self.after(100, self.update_board)
def generate_board(self):
# Draw a square on the game board for every live cell in the grid.
for x in range(0, self.resolution):
for y in range(0, self.resolution):
realx = x * self.size_factor
realy = y * self.size_factor
if self.grid[x][y] == 1:
self.draw_square(realx, realy, self.size_factor)
def draw_square(self, y, x, size):
# Draw a square on the canvas.
self.canvas.create_rectangle(x, y, x+size, y+size, fill='black', outline='black')
def run_generation(self):
# Generate new empty grid to populate with result of generation.
return_grid = [[0 for x in range(self.resolution)] for x in range(self.resolution)]
# Iterate over the grid.
for x in range(0, self.resolution):
for y in range(0, self.resolution):
neighbours = self.number_neighbours(x, y)
if self.grid[x][y] == 1:
# Current cell is alive.
if neighbours < 2:
# Cell dies (rule 1).
return_grid[x][y] = 0
elif neighbours == 2 or neighbours == 3:
# Cell lives (rule 2).
return_grid[x][y] = 1
elif neighbours > 3:
# Cell dies (rule 3).
return_grid[x][y] = 0
else:
# Current cell is dead.
if neighbours == 3:
# Make cell live (rule 4).
return_grid[x][y] = 1
return return_grid
def number_neighbours(self, x, y):
count = 0
'''
Count the number of cells that are alive in the following coordiantes.
-x -y | x -y | +x -y
-x y | | +x y
-x +y | x +y | +x +y
'''
xrange = [x-1, x, x+1]
yrange = [y-1, y, y+1]
for x1 in xrange:
for y1 in yrange:
if x1 == x and y1 == y:
# Don't count this cell.
continue
try:
if self.grid[x1][y1] == 1:
count += 1
except IndexError:
continue
return count
def canvas_click_event(self, event):
# Work out where the mouse is in relation to the grid.
gridx = math.floor((event.y/self.width_and_height)*self.resolution)
gridy = math.floor((event.x/self.width_and_height)*self.resolution)
# Make that cell alive.
self.grid[gridx][gridy] = 1
if __name__ == "__main__":
# Create the class and kick off the Tkinter loop.
tkinter_canvas = game_of_life(500, 50)
tkinter_canvas.mainloop()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment