import tkinter as tk
import random as rd
# Nomenclature
# 0 = Background
# 1 = Electron Head
# 2 = Electorn Tail
# 3 = Wire
# Fist create the background needed to complete
class Universe(object):
# since the example we're given is 26x13 rectangle,
# we have to make sure we have the width and height defined to make dimensions.
def __init__(self, width, height):
self.width = width
self.height = height
self.cells = dict()
for i in range(0, height):
for j in range(0, width):
self.cells[(i, j)] = Cell((i, j), 0, width, height)
def generate_random(self):
for current_cell in self.cells:
self.cells[current_cell].state = rd.randint(0, 3)
# Tried insterting these values, but it didn't work
# """
#
# ..tH....
# . tH....
# .......H .
# ....
# . .....
# HHH.
# ..tH.... t
# . ......
# .Ht.....
#"""
# This is where we interpret all the rules:
def apply_rules(self):
next_state = dict()
# 0 = Background
# 1 = Electron Head
# 2 = Electorn Tail
# 3 = Wire
for current_cell in self.cells:
# Wire changes to electron head if and only if one or two of its neighbors are electron head.
if self.cells[current_cell].state == 3: # wire
if self.cells[current_cell].count_electron_heads(self) == 1: # if there is 1 electron head
next_state[current_cell] = 1 # change to electron head
elif self.cells[current_cell].count_electron_heads(self) == 2:# if there is 2 electron head neighbors
next_state[current_cell] = 1 # change to electron head too
# Otherwise, it remains wire. (use else)
else:
next_state[current_cell] = 3
# Electron tail changes to wire everytime
elif self.cells[current_cell].state == 2:
next_state[current_cell] = 3
# Electron head changes to tail everytime
elif self.cells[current_cell].state == 1:
next_state[current_cell] = 2
# Background remains background
else:
next_state[current_cell] = 0
for current_cell in next_state:
self.cells[current_cell].state = next_state[current_cell]
def plain_text_display(self):
for i in range(0, self.height):
row = list()
for j in range(0, self.width):
row.append(self.cells[(i, j)].state)
print(row)
class Cell(object):
def __init__(self, coordinates, state, universe_width, universe_height):
self.state = state
self.coordinates = coordinates
self.neighborhood = [[self.coordinates[0] - 1, self.coordinates[1] - 1],
[self.coordinates[0] - 1, self.coordinates[1]],
[self.coordinates[0] - 1, self.coordinates[1] + 1],
[self.coordinates[0], self.coordinates[1] - 1],
[self.coordinates[0], self.coordinates[1] + 1],
[self.coordinates[0] + 1, self.coordinates[1] - 1],
[self.coordinates[0] + 1, self.coordinates[1]],
[self.coordinates[0] + 1, self.coordinates[1] + 1]]
for i in range(0, len(self.neighborhood)):
if self.neighborhood[i][0] < 0:
self.neighborhood[i][0] = universe_height - 1
elif self.neighborhood[i][0] > universe_height - 1:
self.neighborhood[i][0] = 0
if self.neighborhood[i][1] < 0:
self.neighborhood[i][1] = universe_width - 1
elif self.neighborhood[i][1] > universe_width - 1:
self.neighborhood[i][1] = 0
def count_electron_heads(self, universe):
electron_heads_count = 0
for neighbor_cell_coordinates in self.neighborhood:
if universe.cells[(neighbor_cell_coordinates[0], neighbor_cell_coordinates[1])].state == 1:
electron_heads_count += 1
return electron_heads_count
class GUI(tk.Tk):
# the graphical display is adapted from:
# https://stackoverflow.com/questions/44826267/setting-tk-frame-width-and-height
# https://python-forum.io/thread-21382.html
# https://gist.github.com/novel-yet-trivial/3eddfce704db3082e38c84664fc1fdf8
# This is the initiation set the colors and everything for the graphical interface
def __init__(self, universe):
tk.Tk.__init__(self)
self.cell_size = 12
self.ui_frame = tk.Frame(self, width=self.cell_size*universe.width, height=60, bg="#282729")
self.ui_frame.pack(fill="x", expand=True)
self.cell_canvas = tk.Canvas(self, width=self.cell_size*universe.width, height=self.cell_size*universe.height,
borderwidth=0, highlightthickness=0)
self.cell_canvas.pack(fill="both", expand=True)
self.cells = dict()
for i in range(0, universe.height):
for j in range(0, universe.width):
# Blue for Electorn Head
if universe.cells[(i, j)].state == 1:
color = "#1a00d2"
# Red for Electron Tail
elif universe.cells[(i, j)].state == 2:
color = "#ff3532"
# Yellow wire for the 3
elif universe.cells[(i, j)].state == 3:
color = "#EDBE02"
# Black for the background (0)
else:
color = "#0C1010"
self.cells[(i, j)] = self.cell_canvas.create_rectangle(j*self.cell_size, i*self.cell_size,
(j+1)*self.cell_size, (i+1)*self.cell_size,
fill=color, tag=universe.cells[(i, j)])
self.draw_button = tk.Button(self.ui_frame, text="Draw", command=lambda: self.draw(universe))
self.draw_button.pack(side="left")
# The updating drawing is just changing the colors
def draw(self, universe):
for i in range(0, universe.height):
for j in range(0, universe.width):
if universe.cells[(i, j)].state == 1:
color = "#1a00d2"
elif universe.cells[(i, j)].state == 2:
color = "#ff3532"
elif universe.cells[(i, j)].state == 3:
color = "#EDBE02"
else:
color = "#0C1010"
self.cells[(i, j)] = self.cell_canvas.create_rectangle(j*self.cell_size, i*self.cell_size,
(j+1)*self.cell_size, (i+1)*self.cell_size,
fill=color, tag=universe.cells[(i, j)])
universe.apply_rules()
self.cell_canvas.itemconfig(self.cells[(i,j)], fill=color)
wireworld = Universe(26,13)
wireworld.generate_random()
g = GUI(wireworld)
g.mainloop()