質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

2320閲覧

2方向にのみ作用するセルオートマトン

suugaku_nyumon

総合スコア37

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2018/12/04 01:32

質問

昨日、2次元セルオートマトンの質問をした者ですが、昨日のセルオートマトンのコードを自分なりに編集して、「上下左右」を考えるものから「左右」のみを考える2方向のセルオートマトンのアニメーションを作成しようと試みました。

下がそのコードですが、「♯実行メイン」、「♯セルの初期設定」、「#セルの色設定」、「#実行メイン」のコードを変更して、初期条件が(1,15)の位置が赤色のセルとなり、赤いセルがあった場合、右のセルが赤いセルとなり、左が赤いセルから黒いセルに変わり、赤いセルが右に移動していくプログラムを作成しようとしました。

要するに最初に(1,15)のセルが赤くなると、次は(2,15)のセルが赤くなり、(1,15)のセルが黒に変わって(3,15)のセルが赤くなり・・・という感じです。

しかし、いざ下のコードを実行しようとすると、初期条件の(1,15)のセルが赤くなり、その後、一番右のセルが赤くなり動作が終わってしまいます。多分原因は「for i in range(1,30):」で同時処理されてしまっているからだと思うのですが、どう変更すれば順番に表示してくれるか分かりません。

コード

Python3

1from tkinter import * 2import time 3import tkinter as tk 4#配列の宣言 5def array2(N1,N2): 6 return [[0 for j in range(N2)]for k in range(N1)] 7def array3(N1,N2,N3): 8 return [array2(N2,N3)for k in range(N1)] 9#セルの初期設定 10def initdt(): 11 A=array3(2,31,31); A[0][1][15]=1 12 return A 13#セルオートマトンの実行 14def execCell(A,i1): 15 for i in range(1,30): 16 if A[i1][i][15]==1: 17 A[i1][i+1][15]=1 18 A[i1][i-1][15]=0 19#セルの位置決めとIDの設定 20def drawCell(canvas,A,k): 21 x2=0 22 CID=array2(31,31) 23 for i in range(1,30): 24 x1=x2 25 x2=x1+10 26 y2=0 27 for j in range(1,30): 28 y1=y2 29 y2=y1+10 30 CID[i][j]=canvas.create_rectangle(x1,y1,x2,y2,fill='black') 31 return CID 32#セルの色設定 33def modifyCell(canvas,A,k,CID): 34 CL=['black','#ff0000'] 35 for i in range(1,30): 36 for j in range(1,30): 37 canvas.itemconfig(CID[i][j],fill=CL[A[k][i][j]]) 38 canvas.itemconfig(CID[i][j],outline=CL[A[k][i][j]]) 39#Tk初期設定 40def initTk(): 41 tk=Tk(); tk.title("2D Cell Automaton"); tk.resizable(0,0) 42 return tk 43#画面キャプチャ用 44def leftMouseDown(event): 45 global canvas, A,k,CID 46 modifyCell(canvas,A,k,CID) 47 execCell(A,k) 48#実行メイン 49A=initdt() 50root=initTk() 51canvas=Canvas(root,width=290,height=290,highlightthickness=0) 52canvas.pack() 53CID=drawCell(canvas,A,0) 54k=0 55 56def animate(): 57 global k 58 modifyCell(canvas, A, k, CID) 59 execCell(A,k) 60 root.after(200, animate) 61 62root.after(200, animate) 63root.mainloop()

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

描画とロジックを混在するとわかりにくいので、分離した方が良いです。
一応サンプルを提示します。

python

1import tkinter as tk 2 3class Cell: 4 width = 30 5 height = 30 6 7 def __init__(self, id, canvas, stat=False): 8 """ 9 stat: False=dead, True=live 10 """ 11 self.id = id 12 self.stat = stat 13 self.top = self.height 14 self.left = id*self.width+self.width 15 self.bottom = self.top+self.height 16 self.right = self.left+self.width 17 self.cid = canvas.create_rectangle(self.left, self.top, self.right, self.bottom, fill='black', outline='lightblue') 18 def draw(self, canvas): 19 if self.stat == False: 20 canvas.itemconfigure(self.cid, fill='black') 21 else: 22 canvas.itemconfigure(self.cid, fill='red') 23 24 def is_live(self): 25 return self.stat 26 def set_live(self): 27 self.stat = True 28 def set_dead(self): 29 self.stat = False 30 31class Frame(tk.Frame): 32 33 canvas=None 34 cells=[] 35 def __init__(self, master=None, title=None, width=100, height=100): 36 tk.Frame.__init__(self, master, height=height, width=width) 37 if title is not None: 38 self.master.title(title) 39 print("title: ", title) 40 self.canvas = tk.Canvas(self,width=width,height=height,highlightthickness=0) 41 for i in range(10): 42 cell=Cell(i,self.canvas,stat=False) 43 self.cells.append(cell) 44 for cell in self.cells: 45 cell.draw(self.canvas) 46 self.canvas.pack() 47 48 def automaton(self, init=5): 49 """ 50 あるルールを元にセルの生き死にを決定する 51 今回は、自分の右隣がLiveの場合自分がLiveになる、Liveの場合はDeadになる 52 """ 53 def check_stat(): 54 """ 55 cellの状態をルールに沿って確認し、各cellがどの状態になるかを返却する 56 """ 57 stats = [False] * len(self.cells) 58 my = self.cells[0] 59 for i, cell in enumerate(self.cells): 60 if i==0: 61 continue 62 stats[i-1] = cell.is_live() 63 stats[i]=my.is_live() # 最後は最初のセルの状態に依存する(ループさせる) 64 #print(stats) 65 66 return stats 67 68 def next_generation(stats): 69 for i, cell in enumerate(self.cells): 70 cell.set_live() if stats[i] else cell.set_dead() 71 cell.draw(self.canvas) 72 73 def exec(): 74 stats = check_stat() 75 next_generation(stats) 76 self.after(1000, exec) 77 78 self.cells[init].set_live() 79 self.after(1000, exec) 80 81if __name__ == "__main__": 82 83 frm = Frame(title='2D Cell Automaton', width=400, height=200) 84 frm.pack() 85 frm.automaton() 86 87 # ループ 88 frm.mainloop() 89

投稿2018/12/04 11:03

t_obara

総合スコア5488

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

suugaku_nyumon

2018/12/04 12:12

ご指摘ありがとうございます。参考にします。
guest

0

ベストアンサー

セルオートマトンとは「一つ前の世代のセルの状態から、次の世代のセルの状態が決まる」というものです。

前回の質問でそれを実現するために適切に書かれていた論理が修正によって一部壊れているようです。

python

1... 2 3# (A) 4# 現在の世代がi1, 次の世代はi2です。 5# この関数ではi1の状態からi2のセル状態を作らねばなりません。 6# 例えばこんな感じに... 7def execCell(A,i1): 8 i2 = 1 - i1 9 for i in range(1, 30): 10 if A[i1][i-1][15] == 1: # 左隣のセルが赤だったら 11 A[i2][i][15] = 1 # 次の世代ではこのセルを赤にする 12 else: 13 A[i2][i][15] = 1 # そうでないならこのセルは黒にする 14 15... 16 17def animate(): 18 global k 19 modifyCell(canvas, A, k, CID) 20 execCell(A,k) 21 k = 1 - k # (B) <==これが抜けてます 22 root.after(200, animate) 23 24...

このプログラムは「現在の世代」をA[k]で表し「次の世代」をA[1 - k]で表しており、1世代ごとにkを0, 1, 0, 1, ...のように切り替えながら任意の世代数の計算をするようになっています。よって(B)に示したようにkの値を更新しないと(例えオートマトンの計算をしても)常に同じ世代を表示し続ける結果になります。

投稿2018/12/04 03:57

編集2018/12/04 03:58
KSwordOfHaste

総合スコア18392

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

suugaku_nyumon

2018/12/04 12:09

ご回答ありがとうございました。何とか解決しました。 プログラムの意味を誤解していました。そのため修正するつもりが論理を壊しておりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問