Life game with Python [I made it] (on the terminal & Tkinter)

This time, I made Conway's Game of Life instead of numerical simulation.

I started with the intention of taking a break, but when I made it, I was addicted to it, so I made a lot of trial and error. Therefore, the finished product is finally in a moving shape. If I understood the specifications, I think I could make something better, but I didn't feel like reading that much. .. ..

Life Game_007

What is Conway's Game of Life?

First, briefly explain about Conway's Game of Life. A life game is a type of cellular automaton that has information that the grid points are "alive" and "dead", and when the time (generation) advances by one, it is inside according to the given rules according to the surrounding situation. It changes the state of. As a typical rule, on a square grid, with respect to points around 8 squares, if 2 or 3 live, it will survive, and if there are 3 surviving grid points around it, it will be newly born. I think there are 3 etc. Since Conway's Game of Life is Turing complete, you can reproduce the computer inside Conway's Game of Life. For more information

<a href="http://ja.wikipedia.org/wiki/%E3%83%A9%E3%82%A4%E3%83%95%E3%82%B2%E3%83%BC%E3% 83% A0 "target =" _ blank "title =" Life Game --Wikipedia: "> Life Game --Wikipedia: Life Game World 1 [ Complex system] --Nico Nico Douga: GINZA:

Please refer to. The video is especially recommended.

Life game on the terminal

I wanted to make a life game using Tkinter, but it seemed to be difficult, so I made the rules of the life game first so that I could check it on the terminal.

That is next.

lifegame_console.py


#! /usr/bin/env python
# -*- coding:utf-8 -*-
#
# written by ssh0, June 2014.

import numpy as np
import sys
import time
import os

class LifeGame:

    def __init__(self, L=50, rule="2 3/3"):
        self.L = L # lattice size
        p = 0.2
        self.survive = [int(i) for i in rule.split("/")[0].split()]
        self.birth = [int(i) for i in rule.split("/")[1].split()]
        lattice = np.random.random([self.L+2, self.L+2])
        self.lattice = lattice<p
        self.lattice[0,:] = self.lattice[self.L+1,:] = False
        self.lattice[:,0] = self.lattice[:,self.L+1] = False

    def canvas_update(self):
        os.system("clear")
        print "\n"
        l = ""
        for y in range(1,self.L+1):
            for x in range(1,self.L+1):
                if self.lattice[x,y]:
                    l += u" ■"
                else:
                    l += u" □"
            l += "\n"
        print l
        print "\n"
        time.sleep(0.1)
                
    def progress(self):
        L = self.L
        Tmax = 2000
        t = 0
        while t < Tmax:
            try:
                self.canvas_update()
                nextsites = []
                
                #Periodic boundary conditions
                self.lattice[0,0] = self.lattice[self.L,self.L]
                self.lattice[0,self.L+1] = self.lattice[self.L,1]
                self.lattice[self.L+1,0] = self.lattice[1,self.L]
                self.lattice[self.L+1,self.L+1] = self.lattice[1,1]
                for m in range(1, self.L+1):
                    self.lattice[m, self.L+1] = self.lattice[m, 1]
                    self.lattice[m, 0] = self.lattice[m, self.L]
                    self.lattice[0, m] = self.lattice[self.L, m]
                    self.lattice[self.L+1, m] = self.lattice[1, m]
                
                #Judgment of adjacent grid points
                for m in range(1,self.L+1):
                    for n in range(1,self.L+1):
                        
                        if self.lattice[m,n]:
                            neighber = np.sum(self.lattice[m-1:m+2, n-1:n+2])-1
                            if neighber in self.survive:
                                nextsites.append((m,n))
                        else:
                            neighber = np.sum(self.lattice[m-1:m+2, n-1:n+2])
                            if neighber in self.birth:
                                nextsites.append((m,n))
                                
                #Update lattice
                self.lattice[:] = False
                for nextsite in nextsites:
                    self.lattice[nextsite] = True
                
                t += 1
                
            except KeyboardInterrupt:
                print "stopped."
                break

if __name__ == '__main__':
    
    lg = LifeGame()
    lg.progress()

The initial condition was that the points below the threshold in the matrix to which random numbers were assigned survived. For the display, I managed to clear the terminal first, and print the surviving sites as ■ and the other sites as □. If I set the delay time to less than 0.1, the flicker became worse in my environment, so I can't seem to make it any faster.

I'm making a video so please

<img src = "https://i.ytimg.com/vi/7KMluy0fRq8/2.jpg " alt = "Easy with Python" I made a Life Game (numpy) "border =" 0 "width =" 145 "height =" 109 "/> I made a simple Life Game with Python (numpy)

Display using Tkinter

Next, I will introduce what I made using Tkinter's Canvas. The most difficult thing to make this was to be able to change the "life" and "death" of each grid by clicking. It may be easier to do this with Pygame, and as far as I've investigated, I've only seen people using it. However, I think the basics are the same, so I decided to use Tkinter itself, which I will continue to use. All are listed below.

lifegame.py


#! /usr/bin/env python
# -*- coding:utf-8 -*-
#
# written by ssh0, September 2014.

from tkinter import *
import numpy as np
import sys
# import time


class LifeGame:

    def __init__(self, L=30, rule="2 3/3", p=None, pattern=None):
        self.L = L  # lattice size
        self.survive = [int(i) for i in rule.split("/")[0].split()]
        self.birth = [int(i) for i in rule.split("/")[1].split()]

        if p:
            lattice = np.random.random([self.L + 2, self.L + 2])
            self.lattice = lattice < p
            self.lattice[0, :] = self.lattice[self.L+1, :] = False
            self.lattice[:, 0] = self.lattice[:, self.L + 1] = False
        else:
            self.lattice = np.zeros([self.L + 2, self.L + 2], dtype=bool)
            if pattern:
                for x, y in pattern:
                    self.lattice[x, y] = True

    def progress(self, canvas_update, update):
        Tmax = 2000
        t = 0
        self.loop = True
        while self.loop:
            try:
                past_lattice = self.lattice.copy()

                nextsites = []

                #Periodic boundary conditions
                self.lattice[0, 0] = self.lattice[self.L, self.L]
                self.lattice[0, self.L + 1] = self.lattice[self.L, 1]
                self.lattice[self.L + 1, 0] = self.lattice[1, self.L]
                self.lattice[self.L + 1, self.L + 1] = self.lattice[1, 1]
                for m in range(1, self.L+1):
                    self.lattice[m, self.L+1] = self.lattice[m, 1]
                    self.lattice[m, 0] = self.lattice[m, self.L]
                    self.lattice[0, m] = self.lattice[self.L, m]
                    self.lattice[self.L+1, m] = self.lattice[1, m]

                #Judgment of adjacent grid points
                for m in range(1, self.L + 1):
                    for n in range(1, self.L + 1):

                        if self.lattice[m, n]:
                            neighber = np.sum(self.lattice[m-1:m+2, n-1:n+2])-1
                            if neighber in self.survive:
                                nextsites.append((m, n))
                        else:
                            neighber = np.sum(self.lattice[m-1:m+2, n-1:n+2])
                            if neighber in self.birth:
                                nextsites.append((m, n))

                #Update lattice
                self.lattice[:] = False
                for nextsite in nextsites:
                    self.lattice[nextsite] = True

                #Drawing update
                changed_rect = np.where(self.lattice != past_lattice)
                for x, y in zip(changed_rect[0], changed_rect[1]):
                    if self.lattice[x, y]:
                        color = "green"
                    else:
                        color = "black"
                    canvas_update(x, y, color)
                update()
               # time.sleep(0.1)

                t += 1
                if t > Tmax:
                    self.loop = False

            except KeyboardInterrupt:
                print("stopped.")
                break


class Draw_canvas:

    def __init__(self, lg, L):

        self.lg = lg
        self.L = L
        default_size = 640  # default size of canvas
        self.r = int(default_size / (2 * self.L))
        self.fig_size = 2 * self.r * self.L
        self.margin = 10
        self.sub = Toplevel()
        self.sub.title("Life Game")
        self.canvas = Canvas(self.sub, width=self.fig_size + 2 * self.margin,
                             height=self.fig_size + 2 * self.margin)
        self.c = self.canvas.create_rectangle
        self.update = self.canvas.update
        self.rects = dict()
        for y in range(1, self.L + 1):
            for x in range(1, self.L + 1):
                if self.lg.lattice[x, y]:
                    live = True
                else:
                    live = False
                tag = "%d %d" % (x, y)
                self.rects[tag] = Rect(x, y, live, tag, self)
        self.canvas.pack()

    def canvas_update(self, x, y, color):
        v = self.rects["%d %d" % (x, y)]
        v.root.canvas.itemconfig(v.ID, fill=color)


class Rect:

    def __init__(self, x, y, live, tag, root):
        self.root = root
        self.x = x
        self.y = y
        self.live = bool(live)
        if live:
            color = "green"
        else:
            color = "black"
        self.ID = self.root.c(2*(x-1)*self.root.r + self.root.margin,
                              2*(y-1)*self.root.r + self.root.margin,
                              2*x*self.root.r + self.root.margin,
                              2*y*self.root.r + self.root.margin,
                              outline="#202020", fill=color, tag=tag)
        self.root.canvas.tag_bind(self.ID, '<Button-1>', self.pressed)

    def pressed(self, event):
        if self.live:
            self.live = False
            color = "black"
        else:
            self.live = True
            color = "green"
        self.root.lg.lattice[self.x, self.y] = self.live
        self.root.canvas.itemconfig(self.ID, fill=color)


class TopWindow:

    def show_window(self, title="title", *args):
        self.root = Tk()
        self.root.title(title)
        frames = []
        for i, arg in enumerate(args):
            frames.append(Frame(self.root, padx=5, pady=5))
            for k, v in arg:
                Button(frames[i], text=k, command=v).pack(expand=YES, fill='x')
            frames[i].pack(fill='x')
        self.root.mainloop()


class Main:

    def __init__(self):
        L = 100
        rule = "2 3/3"
        self.top = TopWindow()
        c = L / 2
        #Die hard
        pattern = [(c-1, c+1), (c, c+1), (c, c+2), (c+4, c+2),
                   (c+5, c), (c+5, c+2), (c+6, c+2)]

        self.lg = LifeGame(L, rule, p=None, pattern=pattern)
        self.top.show_window("Life game", (('set', self.init),),
                             (('start', self.start),
                              ('pause', self.pause)),
                             (('save', self.pr),),
                             (('quit', self.quit),))

    def init(self):
        self.DrawCanvas = Draw_canvas(self.lg, self.lg.L)

    def start(self):
        self.lg.progress(self.DrawCanvas.canvas_update, self.DrawCanvas.update)

    def pause(self):
        self.lg.loop = False

    def pr(self):
        import tkinter.filedialog
        import os
        if self.DrawCanvas is None:
            return 1
        fTyp = [('eps file', '*eps'), ('all files', '*')]
        filename = tkinter.filedialog.asksaveasfilename(filetypes=fTyp,
                                                  initialdir=os.getcwd(),
                                                  initialfile='figure_1.eps')
        if filename is None:
            return 0
        self.DrawCanvas.canvas.postscript(file=filename)

    def quit(self):
        self.pause()
        sys.exit()

if __name__ == '__main__':

    app = Main()

The difference from the previous lifegame_console.py is that the handling of small variables in LifeGame.init, canvas_update is set to another class Draw_canvas, and the part that draws the grid in it is divided into another class Rect. As a result, each grid point can be treated as an independent one, and if you press the grid point, you can switch between "life" and "death". I captured the actual execution, so please have a look (the latter half is just to follow the code connection, so if you are not interested, you can skip it).

<img src = "https://i.ytimg.com/vi/1M9sc5TlWQg/3.jpg " alt = "Life with Python" I made a game [Tkinter] "border =" 0 "width =" 145 "height =" 109 "/> I made a life game with Python [Tkinter]

Summary

This time I'm mostly playing, but I've learned new things and I think that the range of simulations in the future will expand. Also, subtitles and explanations should be added to the video. .. .. I would like to touch it a little more.

Recommended Posts

Life game with Python [I made it] (on the terminal & Tkinter)
I made a simple typing game with tkinter in Python
I made a puzzle game (like) with Tkinter in Python
I made a life game with Numpy
I made a roguelike game with Python
[Python] I made a Youtube Downloader with Tkinter.
I tried playing with the calculator on tkinter
I made a bin picking game with Python
I made something with python that NOW LOADING moves from left to right on the terminal
I tried to implement Minesweeper on terminal with python
I made a Christmas tree lighting game with Python
I made blackjack with python!
I made a Python3 environment on Ubuntu with direnv.
I made blackjack with Python.
I made wordcloud with Python.
Tank game made with python About the behavior of tanks
[Python] I installed the game from pip and played it
[I made it with Python] XML data batch output tool
I made a fortune with Python.
Othello game development made with Python
Life game with Python! (Conway's Game of Life)
I liked the tweet with python. ..
I made a daemon with Python
CUM_plot, which I often see at the manufacturing site, did not fall on the net, so I made it with python
Save the result of the life game as a gif with python
I made a poker game server chat-holdem using websocket with python
I made a segment tree with python, so I will introduce it
I made a program that automatically calculates the zodiac with tkinter
I made a character counter with Python
Download files on the web with Python
I made a Hex map with Python
[Python] A progress bar on the terminal
I made a simple blackjack with Python
I made a configuration file with Python
I made a neuron simulator with Python
[Python] I tried to visualize the night on the Galactic Railroad with WordCloud!
I want to tweet on Twitter with Python, but I'm addicted to it
I set the environment variable with Docker and displayed it in Python
I tried with the top 100 PyPI packages> I tried to graph the packages installed on Python
[Python, ObsPy] I drew a beach ball on the map with Cartopy + ObsPy.
[Python] I analyzed the diary of a first-year member of society and made a positive / negative judgment on the life of a member of society.
I tried "smoothing" the image with Python + OpenCV
[Python] I introduced Word2Vec and played with it.
I made a competitive programming glossary with Python
I made a weather forecast bot-like with Python.
I made a GUI application with Python + PyQt5
I tried "differentiating" the image with Python + OpenCV
GUI image cropping tool made with Python + Tkinter
I made a Twitter fujoshi blocker with Python ①
I want to make a game with Python
I tried "binarizing" the image with Python + OpenCV
Introduction to Python with Atom (on the way)
I made a Mattermost bot with Python (+ Flask)
I installed Pygame with Python 3.5.1 in the environment of pyenv on OS X
I couldn't import the python module with VSCODE, but I could do it on jupyterlab, so I searched for the cause (2)
I tried to make the weather forecast on the official line by referring to the weather forecast bot of "Dialogue system made with python".
I made a Twitter BOT with GAE (python) (with a reference)
〇✕ I made a game
Coordinates of the right end of Label made with tkinter
I tried Python on Mac for the first time.
I made a vim learning game "PacVim" with Go