Skip to content

Instantly share code, notes, and snippets.

@eidas
Created September 13, 2013 05:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save eidas/6546917 to your computer and use it in GitHub Desktop.
Save eidas/6546917 to your computer and use it in GitHub Desktop.
ライフゲーム for Python 2.x
#! /usr/bin/env python
# coding:utf-8
import Tkinter
from copy import *
from random import *
import pickle
'''ライフゲーム ver.3 Tkのキャンバス上にライフゲームのボードを再現してみる'''
def fileopen(lifeboard, filepath):
"""保存にシリアライズを使えた場合には、デシリアライズで対応"""
f=open(filepath, "r")
lifeboard.xmax = int(f.readline().split("=")[1])
lifeboard.ymax = int(f.readline().split("=")[1])
lifeboard.gen = int(f.readline().split("=")[1])
lifeboard.board = eval(f.readline().split("=")[1])
lifeboard.recalc_lives()
f.close()
def filesave(lifeboard, filepath):
"""理想的にはシリアライズの方がよいか"""
if isinstance(lifeboard, Lifeboard) == False :
return
f=open(filepath, "w")
s = ["lifeboard.xmax=" + str(lifeboard.xmax()) + "\n",
"lifeboard.ymax=" + str(lifeboard.ymax()) + "\n",
"lifeboard.gen=" + str(lifeboard.gen) + "\n",
"lifeboard.board=" +str(lifeboard.board) + "\n"]
f.writelines(s)
f.close()
def num(bd, x, y):
return sum((bd[x-1][y-1], bd[x ][y-1], bd[x+1][y-1],
bd[x-1][y ] , bd[x+1][y ],
bd[x-1][y+1], bd[x ][y+1], bd[x+1][y+1]))
'''ライフゲームの盤を定義。2次元配列で盤を定義する。盤の大きさがm×nの時、(m+2)×(n+2)の大きさの配列を用意し、外周をとる。'''
class Lifeboard(object):
"クラスの初期化では、存在セル位置の列挙リストを渡して初期化する"
lifetile = "■ "
nonetile = ". "
def __init__(self, m, n):
self.board = []
self.prevboard = []
self.prev2board = []
self.Xmax = m
self.Ymax = n
self.gen = 1
self.lives = 0
self.board = [0]*(self.Ymax + 2)
for j in range(0, self.Ymax + 2):
self.board[j] = [0]*(self.Xmax+2)
def random_init(self, frequency):
self.lives = 0
for j in range(1, self.Ymax + 1):
for i in range(1, self.Xmax + 1):
if (random() < frequency) :
self.board[j][i] = 1
self.lives += 1
else:
self.board[j][i] = 0
def nextgen(self):
"""if self.prevboard != None :"""
self.prev2board = deepcopy(self.prevboard)
self.prevboard = deepcopy(self.board)
self.lives = 0
for j in range(1, self.Ymax + 1):
for i in range(1, self.Xmax + 1):
count = num(self.prevboard, j, i)
if self.prevboard[j][i] :
self.board[j][i] = (0, 0, 1, 1, 0, 0, 0, 0, 0)[count]
else:
self.board[j][i] = (0, 0, 0, 1, 0, 0, 0, 0, 0)[count]
self.lives += self.board[j][i]
self.gen = self.gen + 1
def is_patterned(self):
if self.prev2board != None and self.prev2board == self.board :
return True
else:
return False
def recalc_lives(self):
self.lives = 0
for j in range(1, self.Ymax + 1):
for i in range(1, self.Xmax + 1):
self.lives += self.board[j][i]
def len(self):
return len(self.board)
def xmax(self):
return self.Xmax
def ymax(self):
return self.Ymax
def board(self):
return self.board
def lives(self):
return self.lives
def __repr__(self):
return self.__str__()
def __str__(self):
s = ""
s = "" + "Generation: " + str(self.gen) + " , Lives: " + str(self.lives) + "\n"
for j in range(1, self.Ymax + 1):
for i in range(1, self.Xmax + 1):
if self.board[j][i] :
s = s + self.lifetile
else:
s = s + self.nonetile
s = s + "\n"
return s
class Lifecanvas(object):
status = 0 #0:stop 1:start
width = 0
height = 0
lifeboard = None
canvas = None
unit_xy = 0
def calcunit(self):
lf = self.lifeboard
unitx = int(self.width / lf.xmax())
unity = int(self.height / lf.ymax())
self.unit_xy = unitx if unitx <= unity else unity
def drawtext(self):
tb = self.tb
tb.delete("1.0",Tkinter.END)
s = "Generation: " + str(self.lifeboard.gen) + " , Lives: " + str(self.lifeboard.lives) + "\n"
tb.insert("insert", self.lifeboard)
def drawmap(self):
c = self.canvas
c.delete('all')
lb = self.lifeboard.board
ut = self.unit_xy
for j, row in enumerate(lb):
for i, col in enumerate(row):
if col :
c.create_rectangle(i * ut, j * ut, i * ut + ut - 1, j * ut + ut - 1, fill='green')
def drawboard(self):
self.drawtext()
self.drawmap()
def startstop(self):
if self.status :
self.status = 0
else:
self.status = 1
self.canvas.after(0, self.animate)
def step(self):
if self.status == 0 :
self.lifeboard.nextgen()
self.drawboard()
def animate(self):
self.lifeboard.nextgen()
self.drawboard()
if self.lifeboard.is_patterned() :
self.status = 0
if self.status :
msec = self.scale.get()
self.canvas.after(msec if msec > 0 else 1, self.animate)
def command_fileopen(self):
fileopen(self.lifeboard, "C:\scripts\life.txt")
self.drawboard()
print "File Loaded."
def command_filesave(self):
filesave(self.lifeboard, "C:\scripts\life.txt")
print "File Saved."
def __init__(self, w, h, lifeboard):
tk = Tkinter
self.width = w
self.height = h
self.lifeboard = lifeboard
self.calcunit()
self.window = tk.Tk()
win = self.window
'''メニュー'''
menu1 = tk.Menu(win)
menu1.add_command(label="ファイルを開く",command=self.command_fileopen)
menu1.add_command(label="ファイルに保存",command=self.command_filesave)
menu1.add_separator()
menu1.add_command(label="終了",command=self.window.quit)
menu0=tk.Menu(win)
menu0.add_cascade(label="ファイル",menu=menu1)
win.configure(menu=menu0)
'''テキストボックス'''
self.tb = tk.Text(win, width = 40, height = 1)
self.drawtext()
self.tb.pack()
'''キャンバス'''
self.canvas = tk.Canvas(win, bg = "white",
width = w+10, height = h+10)
self.drawboard()
self.canvas.pack()
'''ツールボックス'''
self.scale = tk.Scale(win,label="実行間隔(msec)",to=500,tickinterval=100,orient="horizontal",
length=300)
self.scale.set(100)
self.scale.pack()
'''コントロールボタン'''
quit_button = tk.Button(win, text = "終了",
command = self.window.quit)
quit_button.pack(side = tk.RIGHT)
step_button = tk.Button(win, text = "ステップ",
command = self.step)
step_button.pack(side = tk.LEFT)
startstop_button = tk.Button(win, text = "開始/停止",
command = self.startstop)
startstop_button.pack(side = tk.BOTTOM)
self.window.mainloop()
#メインループ
life = Lifeboard(50,50)
life.random_init(0.2)
print str(life.xmax())
print str(life.ymax())
lc = Lifecanvas(300, 300, life)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment