【リスト3-1】 シェルピンスキのギャスケットを描く from tkinter import * root=Tk();root.title("Cell Automaton 1D") canvas=Canvas(root, width=280, height=258) canvas.pack() MAXLOOP=256; NLOOP=MAXLOOP+2 Cells=[[0 for i in range(NLOOP)] for j in range(2)] def procDraw(): global NLOOP, MAXLOOP, Cells, canvas for i in range(NLOOP): Cells[0][i]=0; Cells[1][i]=0 Cells[0][1]=1 canvas.create_rectangle(1,1,1,1, fill="red", outline="") k2=0 for i in range(2, MAXLOOP+1): k1=k2; k2=1-k2 #現時刻,次時刻の添字切り替え for j in range(1, i+2): if Cells[k1][j-1] and Cells[k1][j] : Cells[k2][j]=0 elif not Cells[k1][j-1] and Cells[k1][j] : Cells[k2][j]=1 elif Cells[k1][j-1] and not Cells[k1][j]: Cells[k2][j]=1 else: Cells[k2][j]=0 if Cells[k2][j]!=0: canvas.create_rectangle(j,i,j,i, fill="red", outline="") #メイン処理 procDraw() 【リスト3-2】 一次元自己増殖モデル from tkinter import * root=Tk();root.title("Cell Automaton 1D 拡張") canvas=Canvas(root, width=280, height=138) canvas.pack() MAXLOOP=256; NLOOP=MAXLOOP+2 Cells=[[0 for i in range(NLOOP)] for j in range(2)] Ctab=("#FFFFFF", "#0000FF", "#007700", "#FF0000","#770077") FN=0 # 式のタイプ(0~2) MD=2 # 法 2~5 def procDraw(): global NLOOP, MAXLOOP, Cells, canvas, FN, MD for i in range(NLOOP): Cells[0][i]=0; Cells[1][i]=0 j1=int(MAXLOOP/2); j2=j1; i=1 Cells[0][j1]=1; k1=0; k2=0 C=Ctab[Cells[k1][j1]] canvas.create_rectangle(i,j1,i,j1, fill=C, outline="") while j1>1 and j2",leftMouseDown) #root.mainloop() while 1: # 一回ごとの処理 modifyCell(canvas,A,k,CID); execCell(A,k,1-k,5) wait(); k=1-k 3.3 ライフゲーム 【リスト3-4】 ライフゲーム from tkinter import * import time, random #■配列の宣言 def array2(N1,N2): return [[0 for j in range(N2)]for k in range(N1)] def array3(N1,N2,N3): return [array2(N2,N3)for k in range(N1)] #■セルの初期設定 def initdt(): A=array3(2,31,31) for i in range(300): x=int(random.random()*30+1); y=int(random.random()*30+1) A[0][x][y]=1 return A #■セルオートマトンの実行 def execCell(A,i1, i2, Mod): for i in range(1, 30): for j in range(1,30): count=0 for ii in range(i-1,i+2): for jj in range(j-1, j+2): if (ii!=i or jj!=j) and (A[i1][ii][jj]!=0): count+=1 if A[i1][i][j]!=0: if(count==2 or count==3): A[i2][i][j]=1 else: A[i2][i][j]=0 else : if count==3: A[i2][i][j]=1 else: A[i2][i][j]=0 #■セルの位置決めとIDの設定 def drawCell(canvas,A, k): x2=0; CID=array2(31,31) for i in range(1,30): x1=x2; x2=x1+10; y2=0 for j in range(1,30): y1=y2; y2=y1+10 CID[i][j]=canvas.create_rectangle(x1,y1,x2,y2,fill='white') return CID #■セルの色設定 def modifyCell(canvas,A, k,CID): CL=['white','#007700'] # ,'#ff0000','#00ff00','#0000FF'] for i in range(1,30): for j in range(1,30): canvas.itemconfig(CID[i][j], fill=CL[A[k][i][j]]) canvas.itemconfig(CID[i][j], outline=CL[A[k][i][j]]) for i in range(1,30): for j in range(1,30): canvas.itemconfig(CID[i][j], fill=CL[A[k][i][j]]) canvas.itemconfig(CID[i][j], outline=CL[A[k][i][j]]) #■Tk初期設定 def initTk(): tk=Tk(); tk.title("2D Cell Automaton") tk.resizable(0,0) return tk #■待ち処理等 def wait(): root.update_idletasks(); root.update(); time.sleep(0.2) #■画面キャプチャ用 def leftMouseDown(event): global canvas, A,k,CID modifyCell(canvas,A,k,CID); execCell(A,k,1-k,5) k=1-k #■実行メイン A=initdt(); root=initTk() canvas=Canvas(root,width=290,height=290,highlightthickness=0) canvas.pack(); root.update() CID=drawCell(canvas,A,0); k=0 #画面キャプチャのとき以下2行のコメントを外す #canvas.bind("",leftMouseDown) #root.mainloop() while 1: # 一回ごとの処理 modifyCell(canvas,A,k,CID); execCell(A,k,1-k,5) wait(); k=1-k 3.4 食物連鎖 【リスト3-5】 食物連鎖 # -*- coding: UTF-8 -*- #---------------------------------------- #■ N巴の食物連鎖(food chain of N cycles) #---------------------------------------- from tkinter import * from tkinter import messagebox import random,math, time #■配列として用いるリスト宣言 def array(N1, N2=0, N3=0): if N2 == 0 and N3==0:return [0 for i in range(N1)] elif N3 == 0: return [[0 for i in range(N2)] for j in range(N1)] else: return [[[0 for i in range(N3)] for j in range(N2)] for k in range(N1)] #■共通データ MAX = 101 # セル数+1 MD = 8 # サイクル数 EP = 0.5 # 敵に食べられる確率。EP=1にすると幾何学模様に近くなります。 dt=array(2,MAX+1,MAX+1) # 計算用セルデータ # 0   1  2 3 cTab=("#FF0000","#0000FF","#FFFF00","#FF00FF",    "#FFFFFF","#007755","#FF7700","#770077",    "#770000","#000077","#777700","#007700",    "#777777","#00FF77","#FF77FF","#FF0077") hist=array(201) # 履歴格納用配列 avg4=array(201) # 20回平均格納用 dspArea=array(MAX+1,MAX+1) # 表示セル用配列 MAXMAX=(MAX-1)*(MAX-1) # 全体個体数 avrN=MAXMAX/MD # 平均個体数 avLine=MAXMAX/40+30 # グラフ表示平均位置 cur=0 # 現在のセルを示す Vline=199 # 200回毎のグラフ位置を示す縦線の位置 for i in range(MAX+1): # 計算用セルデータの初期設定 for j in range(MAX+1): dt[cur][i][j]= int(random.random() * MD + 1) for i in range(201): # 履歴、20回平均初期設定 hist[i]=avrN;avg4[i]=avrN #■個体数をグラフ表示する生物1の個体数のカウント def count1(): C=0 for i in range(MAX): for j in range(MAX): if dt[cur][i][j]==1: C+=1 return C #■履歴データ設定 def setHist(V): for i in range(1,200): hist[i-1]=hist[i]; avg4[i-1]=avg4[i] hist[199]=V # 値の登録 av=0 # 過去20回の平均値計算と平均値登録 j=199 for i in range(20): av+=hist[j]; j-=1 avg4[199]= int(float(av)/20.0+0.5) #■グラフ表示用XY座標設定 def setHistXY(hist, i): global avrN, avLine return [i+20, avLine-(hist[i]-avrN)/50] #■最初の表示 def initDraw(): global canvas, MAX,HSgraph, AVgraph, Vline, VlineX,txtDsp canvas.delete("DT") for i in range(1,MAX): for j in range(1,MAX): X=i*2+20; Y=j*2+10 dspArea[i][j]=canvas.create_rectangle(X, Y, X+2, Y+2, fill=cTab[dt[cur][i][j]-1], outline="", tag="DT") # 生物1の個体数変化の表示 V=count1(); setHist(V) canvas.create_rectangle(20,220,220,340, fill="#FFFFFF", outline='black',width=2, tag="DT") # 過去4回平均 XY=[] for i in range(200): XY.append(setHistXY(avg4, i)) AVgraph=canvas.create_line(XY, fill="#007700", tag="DT") # 履歴表示 XY=[] for i in range(200): XY.append(setHistXY(hist, i)) HSgraph=canvas.create_line(XY, fill=cTab[0], tag="DT") # 3,000, 5,000, 7,000の線を表示 canvas.create_line(20,320,220,320, fill="#000077", tag="DT") canvas.create_line(20,280,220,280, fill="#000077", tag="DT") canvas.create_line(20,240,220,240, fill="#000077", tag="DT") VlineX = canvas.create_line(Vline+20,240,Vline+20, 340, fill="#000077", tag="DT") Vline-=1 if Vline<0 : Vline=199 # 数値表示 txtDsp=canvas.create_text(120, 230, text="%d 個体数変化(赤) 20回平均(緑) %d" % (V, avg4[199]), font=('sans-serif', '8'), tag="DT") #■2回目以降のセル表示(セルの色変更) def draw(): global canvas, MAX,HSgraph, AVgraph, Vline, VlineX,txtDsp for i in range(1,MAX): for j in range(1,MAX): X=i+20; Y=j+10 CC=cTab[dt[cur][i][j]-1] # 以下の1行の判定でかなり速くなる if CC != canvas.itemcget(dspArea[i][j], option='fill'): canvas.itemconfig(dspArea[i][j], fill=CC) #■2回目以降のグラフ表示(表示が変わる部分のみ) def drawGraph(): global canvas, MAX,HSgraph, AVgraph, Vline, VlineX,txtDsp V=count1(); setHist(V) XY=[] # 過去4回平均 for i in range(200): XY.append(setHistXY(avg4, i)) canvas.delete(AVgraph) AVgraph=canvas.create_line(XY, fill="#007700", tag="DT") XY=[] # 履歴表示 for i in range(200): XY.append(setHistXY(hist, i)) canvas.delete(HSgraph) HSgraph=canvas.create_line(XY, fill=cTab[0], tag="DT") canvas.coords(VlineX, Vline+20,240,Vline+20, 340) #区切り Vline-=1 if Vline<0 : Vline=199 canvas.itemconfig(txtDsp, # 数値表示            text="%d 個体数変化(赤) 20回平均(緑) %d" %            (V, avg4[199])) #■食物連鎖のシミュレーション def simChain(): global cur nxt=1-cur for i in range(1,MAX): for j in range(1,MAX): dt[nxt][i][j]=dt[cur][i][j] if random.random()< EP : for k in range(1,MD+1): KF = k + 1 if k== MD: KF = 1 if dt[cur][i][j]==k : if(dt[cur][i ][j-1]==KF or dt[cur][i ][j+1]==KF or dt[cur][i-1][j ]==KF or dt[cur][i+1][j ]==KF) : dt[nxt][i][j]=KF cur=nxt #■メイン処理 root=Tk();root.title("N巴の食物連鎖(N= %d)" % MD ) canvas=Canvas(root, width=260,height=400) canvas.pack(); simChain();initDraw();root.update() while True: simChain(); draw(); drawGraph() time.sleep(0.01) root.update()