Skip to content

Instantly share code, notes, and snippets.

@lvidarte
Created June 9, 2017 06:01
Show Gist options
  • Save lvidarte/0cc1cbc6f145469ff373376fc382b1e0 to your computer and use it in GitHub Desktop.
Save lvidarte/0cc1cbc6f145469ff373376fc382b1e0 to your computer and use it in GitHub Desktop.
#!/usr/bin/python3
"""
Author: Leo Vidarte <http://nerdlabs.com.ar>
This is free software,
you can redistribute it and/or modify it
under the terms of the GPL version 3
as published by the Free Software Foundation.
"""
"""
Las transiciones dependen del número de células vecinas vivas:
* Una célula muerta con exactamente 3 células vecinas vivas "nace"
(al turno siguiente estará viva).
* Una célula viva con 2 ó 3 células vecinas vivas sigue viva.
* En otro caso muere o permanece muerta (por "soledad" o "superpoblación").
"""
import tkinter as tk
class Life(tk.Frame):
def __init__(self, board, cell_size=20):
super(Life, self).__init__(tk.Tk())
self.master.title("Game of Life")
self.grid()
self.board = board
self.cell_size = cell_size
self.create_widgets()
self.draw_grid()
self.cells_alive = {}
self.draw_cell(1, 1)
self.mainloop()
def create_widgets(self):
width, height = self.board.size()
kwargs = {
'width' : width * self.cell_size,
'height': height * self.cell_size,
'bg' : 'white',
}
self.canvas = tk.Canvas(self, **kwargs)
self.canvas.grid()
def draw_grid(self):
self.draw_vertical_lines()
self.draw_horizontal_lines()
def draw_vertical_lines(self, color='gray'):
width, height = self.board.size()
for i in range(width - 1):
x = (self.cell_size * i) + self.cell_size
y0 = 0
y1 = self.cell_size * height
self.canvas.create_line(x, y0, x, y1, fill=color)
def draw_horizontal_lines(self, color='gray'):
width, height = self.board.size()
for i in range(height - 1):
x0 = 0
x1 = self.cell_size * width
y = (self.cell_size * i) + self.cell_size
self.canvas.create_line(x0, y, x1, y, fill=color)
def draw_cell(self, x, y, color='black'):
x0 = x * self.cell_size
y0 = y * self.cell_size
x1 = x0 + self.cell_size
y1 = y0 + self.cell_size
args = (x0, y0, x1, y1)
_id = self.canvas.create_rectangle(*args, width=0, fill=color)
self.cells_alive[(x, y)] = _id
self.board.set_alive(x, y)
class Board:
DEAD = 0
ALIVE = 1
def __init__(self, width=8, height=8):
self._width = width
self._height = height
self.set(self._get_empty_board_list())
def set(self, board_list):
self._board_list = [row[:] for row in board_list] # deep copy
self._width = len(board_list[0])
self._height = len(board_list)
def _get_empty_board_list(self):
return [[self.DEAD] * self._width for _ in range(self._height)]
def get(self):
return self._board_list
def size(self):
return (self._width, self._height)
def count_neighbors_alive(self, x, y):
x_center, y_center = x, y
x_left = x_center-1 if x_center-1 >= 0 else self._width-1
x_right = x_center+1 if x_center+1 < self._width else 0
y_up = y_center-1 if y_center-1 >= 0 else self._height-1
y_down = y_center+1 if y_center+1 < self._height else 0
return (self._board_list[y_up][x_left],
self._board_list[y_up][x_center],
self._board_list[y_up][x_right],
self._board_list[y_center][x_left],
self._board_list[y_center][x_right],
self._board_list[y_down][x_left],
self._board_list[y_down][x_center],
self._board_list[y_down][x_right]).count(self.ALIVE)
def get_next_cell_state(self, cell_state, neighbors_alive):
if (cell_state == self.DEAD and neighbors_alive == 3) or \
(cell_state == self.ALIVE and neighbors_alive in (2, 3)):
return self.ALIVE
else:
return self.DEAD
def tick(self):
board_list = self._get_empty_board_list()
for x in range(self._width):
for y in range(self._height):
cell_state = self._board_list[y][x]
neighbors_alive = self.count_neighbors_alive(x, y)
args = (cell_state, neighbors_alive)
board_list[y][x] = self.get_next_cell_state(*args)
self._board_list = board_list
def set_alive(self, x, y):
self._board_list[y][x] = self.ALIVE
if __name__ == '__main__':
board = Board(width=20, height=20)
life = Life(board, cell_size=30)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment