Created
October 4, 2016 16:17
-
-
Save aq1/f8941b2c1edc7d5565ffc51f6cf5ffb4 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Game of life | |
# Dead cell comes alive only if 3 neighbor cells are alive | |
# Live cell stays alive only if there are 2 or 3 live neighbor cells, else it dies | |
# dynamic grid size | |
from tkinter import * | |
from tkinter import font | |
import time | |
import random | |
class GameOfLife(Frame): | |
def __init__(self, parent): | |
Frame.__init__(self, parent) | |
self.parent = parent | |
self.grid(row=0, column=0) | |
self.size_x = 40 | |
self.size_y = 28 | |
self.cell_buttons = [] | |
self.generate_next = True | |
self.initialUI() | |
def initialUI(self): | |
self.parent.title("Game of Life") | |
# frame for title and line of instruction | |
self.title_frame = Frame(self.parent) | |
self.title_frame.grid(row=0, column=0, columnspan=4) | |
self.titleFont = font.Font(family="Helvetica", size=14) | |
title = Label(self.title_frame, text="Conway's Game of Life", font=self.titleFont) | |
title.pack(side=TOP) | |
prompt = Label(self.title_frame, text="Click the cells to create the starting configuration, the press Start Game:") | |
prompt.pack(side=BOTTOM) | |
# creates grid of buttons for starting configuration | |
self.build_grid() | |
# creates a button to start the simulation | |
self.start_button = Button(self.parent, text="Start Game", command=self.simulate_game) | |
self.start_button.grid(row=1, column=1, sticky=E) | |
self.reset_button = Button(self.parent, text="Reset", state=DISABLED, command=self.reset_game) | |
self.reset_button.grid(row=1, column=2, sticky=W) | |
def build_grid(self): | |
# creates new frame for grid of cells in game | |
self.game_frame = Frame( | |
self.parent, width=self.size_x + 2, height=self.size_y + 2, borderwidth=1, relief=SUNKEN) | |
self.game_frame.grid(row=2, column=0, columnspan=4) | |
# instantiates buttons for choosing initial configuration | |
self.cell_buttons = [[Button(self.game_frame, bg="white", width=2, height=1) | |
for i in range(self.size_x + 2)] for j in range(self.size_y + 2)] | |
# creates 2d array of buttons for grid | |
for i in range(1, self.size_y + 1): | |
for j in range(1, self.size_x + 1): | |
self.cell_buttons[i][j].grid(row=i, column=j, sticky=W + E) | |
self.cell_buttons[i][j]['command'] = lambda i=i, j=j: self.cell_toggle(self.cell_buttons[i][j]) | |
mid_x = self.size_x // 2 | |
mid_y = self.size_y // 2 | |
z = 7 | |
for i in range(-z, z): | |
for j in range(-z, z): | |
self.cell_buttons[mid_y + j][mid_x + i]['bg'] = 'black' | |
def simulate_game(self): | |
self.disable_buttons() | |
# creates list of buttons in grid to toggle | |
buttons_to_toggle = [] | |
for i in range(1, self.size_y + 1): | |
for j in range(1, self.size_x + 1): | |
coord = (i, j) | |
# if cell dead and has 3 neighbors, add coordinate to list of coords to toggle | |
if self.cell_buttons[i][j]['bg'] == "white" and self.neighbor_count() == 3: | |
buttons_to_toggle.append(coord) | |
# if cell alive and does not have 2 or 3 neighbors,, add coordinate to list of coords to toggle | |
elif self.cell_buttons[i][j]['bg'] == "black" and self.neighbor_count() != 3 and self.neighbor_count() != 2: | |
buttons_to_toggle.append(coord) | |
# updates (toggles) the cells on the grid | |
for coord in buttons_to_toggle: | |
self.cell_toggle(self.cell_buttons[coord[0]][coord[1]]) | |
if self.generate_next: | |
self.after(100, self.simulate_game) | |
else: | |
self.enable_buttons() | |
def disable_buttons(self): | |
if self.cell_buttons[1][1] != DISABLED: | |
for i in range(0, self.size_y + 2): | |
for j in range(0, self.size_x + 2): | |
self.cell_buttons[i][j].configure(state=DISABLED) | |
self.reset_button.configure(state=NORMAL) | |
self.start_button.configure(state=DISABLED) | |
def enable_buttons(self): | |
# resets game | |
for i in range(0, self.size_y + 2): | |
for j in range(0, self.size_x + 2): | |
self.cell_buttons[i][j]['bg'] = "white" | |
self.cell_buttons[i][j].configure(state=NORMAL) | |
self.reset_button.configure(state=DISABLED) | |
self.start_button.configure(state=NORMAL) | |
self.generate_next = True | |
def gauss(self): | |
coords = [] | |
for _ in range(8): | |
x = int(random.gauss(self.size_y / 2, self.size_y / 3)) | |
y = int(random.gauss(self.size_x / 2, self.size_x / 3)) | |
while self.size_y <= x or x < 0: | |
x = int(random.gauss(self.size_y / 2, self.size_y / 2)) | |
while self.size_x <= y or y < 0: | |
y = int(random.gauss(self.size_x / 2, self.size_x / 2)) | |
coords.append((x, y)) | |
return sum([1 for x, y in coords if self.cell_buttons[x][y]['bg'] == "black"]) | |
def neighbor_count(self): | |
return self.gauss() | |
def cell_toggle(self, cell): | |
if cell['bg'] == "white": | |
cell['bg'] = "black" | |
else: | |
cell['bg'] = "white" | |
def reset_game(self): | |
self.generate_next = False | |
if __name__ == '__main__': | |
root = Tk() | |
game = GameOfLife(root) | |
root.mainloop() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment