Created
September 13, 2013 05:01
-
-
Save eidas/6546917 to your computer and use it in GitHub Desktop.
ライフゲーム for Python 2.x
This file contains 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
#! /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