Search This Blog

Friday, January 4, 2019

Python version of Game of Life Cellular Automata

Hi again everyone!  I've been busy and have made a nice Game of Life/Cellular Automata program in Python.  It took a couple of hours but here it is.  I used the TK interface for the windows and not a whole lot else, it is, after all a pretty simple program. 

Here are a few screen shots:


I think the red with black borders is pretty.



Here's the program:

from Tkinter import *
from random import randint
from time import sleep
class App:
    """This class is derived, I think, from a TK class and is designed to
    work with the TK environment.
    Requires imports from Tkinter, math, random and time"""
    def __init__(self, master):
        """This class is the whole of the application """
        # Necessary Frames
        frame = Frame(master)
        control_frame = Frame(frame)
        control_frame.grid(row = 0, column = 0, sticky = N)
        canvas_frame = Frame(frame)
        canvas_frame.grid(row =0, column = 1)
        #Application variables
        self.is_running = 0
        self.grid_data = []
        for i in range(160):
            self.grid_data.append([])
            for j in range(160):
                self.grid_data[i].append(0)
        self.color_code = 1
        # 0 = not used, 1 = blue, 2 = black, 3 = red, 4 = green
        self.colors = ['pink','blue','black','red','green']
        self.speed = 5
        self.speeds = [5,2,1,0.2,0.02]
        self.speed_str = ['Really slow','Slower','Slow','Fast','Faster',
                           'Max Speed']
        self.tmpstr = 'Speed:\n'+self.speed_str[self.speed]
       
        #Control FrameWidgets
        self.lab = Label(control_frame, text=self.tmpstr)
        self.lab.pack(side = TOP)
        self.b1 = Button(control_frame, text='Randomize')
        self.b1.config(command=self.randomize)
        self.b1.pack()
        self.b2 = Button(control_frame, text='Start')
        self.b2.config(command=self.go_live)
        self.b2.pack()
       
       
        # The Canvas
        self.canvas = Canvas(canvas_frame, width = 800, height = 800)
        self.canvas.config(bg='white')
        self.canvas.pack()
        frame.pack()
        #Menu's
        menubar = Menu(root)
        menu_1 = Menu(menubar, tearoff=0)
        menu_1.add_command(label='Quit',command=root.destroy)
        menubar.add_cascade(label='File', menu=menu_1)
        menu_2 = Menu(menubar, tearoff=0)
        menu_2.add_command(label='Really slow', command=self.menu_2)
        menu_2.add_command(label='Slower', command=self.menu_3)
        menu_2.add_command(label='Slow', command=self.menu_4)
        menu_2.add_command(label='Fast', command=self.menu_5)
        menu_2.add_command(label='Faster', command=self.menu_6)
        menu_2.add_command(label='Max Speed', command=self.menu_7)
        menubar.add_cascade(label='Speed', menu=menu_2)
        master.config(menu=menubar)
        menu_4 = Menu(menubar, tearoff = 0)
        menu_4.add_command(label='Blue', command=self.color_blue)
        menu_4.add_command(label='Black', command=self.color_black)
        menu_4.add_command(label='Red', command=self.color_red)
        menu_4.add_command(label='Green', command=self.color_grn)
        menubar.add_cascade(label='Color', menu=menu_4)
    def randomize(self):
        """ This function deletes the current data and seeds with a new
        set of randomly placed dots"""
        if self.is_running == 0:
            for i in range(160):
                for j in range(160):
                    self.grid_data[i][j] = 0
            for i in range(2400):
                x = randint(0,159)
                y = randint(0,159)
                self.grid_data[x][y] = 1
            self.canvas.delete(ALL)
            self.update_once()
    def go_live(self):
        """This function stops and starts the simulation."""
        if self.is_running == 0:
            self.b2.config(text='Stop')
            self.is_running = 1
            self.run_sim()
        else:
            self.b2.config(text='Start')
            self.is_running = 0
    def update_once(self):
        """This function draws the screen"""
        for x in range(160):
            for y in range(160):
                if self.grid_data[x][y] == 1:
                    self.canvas.create_rectangle(x*5,y*5,x*5+4,y*5+4,
                            fill=self.colors[self.color_code])
        self.canvas.update()
    def run_sim(self):
        """This is the main loop for the simulation.  Calc new grid,
        copy it, then calls update_once to redraw the screen."""
        new_grid = [] # local variable to store intermediate result
        for i in range(160):
            new_grid.append([])
            for j in range(160):
                new_grid[i].append(0)
        while self.is_running == 1:
            for i in range(160):
                for j in range(160):
                    neigh = self.grid_data[i-1][j-1]
                    neigh += self.grid_data[i][j-1]
                    neigh += self.grid_data[(i+1) % 160][j-1]
                    neigh += self.grid_data[(i+1) % 160][j]
                    neigh += self.grid_data[(i+1) % 160][(j+1) % 160]
                    neigh += self.grid_data[i][(j+1) % 160]
                    neigh += self.grid_data[i-1][(j+1) % 160]
                    neigh += self.grid_data[i-1][j]
                    if neigh < 2 or neigh > 3: # cell dies
                        new_grid[i][j] = 0
                    elif neigh == 3: # cell lives or is born
                        new_grid[i][j] = 1
                    else: # cell is the same as previous tick
                        new_grid[i][j] = self.grid_data[i][j]
            for i in range(160):
                for j in range(160):
                    self.grid_data[i][j] = new_grid[i][j]
            self.canvas.delete(ALL)
            self.update_once()
            if self.speed < 5:
                sleep(self.speeds[self.speed])
    def color_grn(self):
        """This function sets the color of th elines to green and then
        refreshes the screen."""
        self.color_code=4
    def color_red(self):
        """This function sets the color of the lines to red and then
        refreshes the screen."""
        self.color_code=3
       
    def color_black(self):
        """This function sets the color of the lines to black and then
        refreshes the screen."""
        self.color_code=2
    def color_blue(self):
        """This function sets the color of the lines to blue and then
        refreshes the screen."""
        self.color_code = 1
    def menu_2(self):
        """ Sets speed to really slow"""
        self.speed = 0
        self.tmpstr = 'Speed:\n'+self.speed_str[self.speed]
        self.lab.config(text=self.tmpstr)
        self.lab.update()
    def menu_3(self):
        """ Sets speed to slower"""
        self.speed = 1
        self.tmpstr = 'Speed:\n'+self.speed_str[self.speed]
        self.lab.config(text=self.tmpstr)
        self.lab.update()
    def menu_4(self):
        """ Sets speed to Slow"""
        self.speed = 2
        self.tmpstr = 'Speed:\n'+self.speed_str[self.speed]
        self.lab.config(text=self.tmpstr)
        self.lab.update()
    def menu_5(self):
        """ Sets speed to Fast"""
        self.speed = 3
        self.tmpstr = 'Speed:\n'+self.speed_str[self.speed]
        self.lab.config(text=self.tmpstr)
        self.lab.update()
    def menu_6(self):
        """Sets speed to Faster"""
        self.speed = 4
        self.tmpstr = 'Speed:\n'+self.speed_str[self.speed]
        self.lab.config(text=self.tmpstr)
        self.lab.update()
    def menu_7(self):
        """ Sets speed to max speed"""
        self.speed = 5
        self.tmpstr = 'Speed:\n'+self.speed_str[self.speed]
        self.lab.config(text=self.tmpstr)
        self.lab.update()
if __name__ == '__main__':
    root = Tk()
    root.wm_title('Cellular Automata')
    app = App(root)
    root.mainloop()
       

No comments:

Post a Comment