最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python實現(xiàn)生命游戲的示例代碼(tkinter版)

 更新時間:2022年08月04日 11:17:31   作者:Hann Yang  
生命游戲是由劍橋大學(xué)約翰·何頓·康威設(shè)計的計算機程序,一時吸引了各行各業(yè)一大批人的興趣。本文將用Python實現(xiàn)這一游戲,感興趣的可以嘗試一下

生命游戲(Game of Life)

由劍橋大學(xué)約翰·何頓·康威設(shè)計的計算機程序。美國趣味數(shù)學(xué)大師馬丁·加德納(Martin Gardner,1914-2010)通過《科學(xué)美國人》雜志,將康威的生命游戲介紹給學(xué)術(shù)界之外的廣大瀆者,一時吸引了各行各業(yè)一大批人的興趣,這時細胞自動機課題才吸引了科學(xué)家的注意。

游戲概述

用一個二維表格表示“生存空間”,空間的每個方格中都可放置一個生命細胞,每個生命細胞只有兩種狀態(tài):“生”或“死”。用綠色方格表示該細胞為“生”,空格(白色)表示該細胞為“死”?;蛘哒f方格網(wǎng)中綠色部分表示某個時候某種“生命”的分布圖。生命游戲想要模擬的是:隨著時間的流逝,這個分布圖將如何一代一代地變化。死亡太沉重,我想稱它為“湮滅”狀態(tài)。

生存定律

生存空間的每個方格都存在一個細胞,它的周邊緊鄰的8個方格上的稱為鄰居細胞。

(1)當前細胞為湮滅狀態(tài)時,當周圍有3個存活細胞時,則迭代后該細胞變成存活狀態(tài)(模擬繁殖)。

(2)當前細胞為存活狀態(tài)時,當周圍的鄰居細胞少于2個存活時,該細胞變成湮滅狀態(tài)(數(shù)量稀少)。

(3)當前細胞為存活狀態(tài)時,當周圍有3個以上的存活細胞時,該細胞變成湮滅狀態(tài)(數(shù)量過多)。

(4)當前細胞為存活狀態(tài)時,當周圍有2個或3個存活細胞時,該細胞保持原樣。

簡單來說,活細胞Cell看作是‘1’,死Cell看作‘0’,8個鄰居的累加和Sum決定了下一輪的狀態(tài):

“繁殖”:Cell=0,若Sum=3,則Cell=1。

“稀少”:Cell=1,若Sum<2,則Cell=0。

“過多”:Cell=1,若Sum>3,則Cell=0。

“正常”:Cell=1,若Sum=2或3,則Cell=1。

生存空間中生命的繁殖和湮滅,如下圖所示:

圖形結(jié)構(gòu)

在游戲進行中,雜亂無序的細胞會逐漸演化出各種精致、有形的圖形結(jié)構(gòu);這些結(jié)構(gòu)往往有很好的對稱性,而且每一代都在變化形狀。一些形狀一經(jīng)鎖定就不會逐代變化。有時,一些已經(jīng)成形的結(jié)構(gòu)會因為一些無序細胞的“入侵”而被破壞。但是形狀和秩序經(jīng)常能從雜亂中產(chǎn)生出來。

通常會有以下四種狀態(tài):

不動點(fixed points):變化終結(jié)于恒定圖像

交替態(tài)(alternation):圖像出現(xiàn)周期性變化

隨機態(tài)(randomness):圖像變化近乎隨機

復(fù)雜態(tài)(complexity):圖像存在某種復(fù)雜規(guī)律

常見的不動結(jié)構(gòu):

周期變化的結(jié)構(gòu):

逐步趨向湮滅的結(jié)構(gòu):

由一根10個連續(xù)細胞演化出來的周期結(jié)構(gòu):

動態(tài)變化后全部湮滅的結(jié)構(gòu):

移動的飛船:周期變化且逐漸向右平移

飛船到了邊界變成向?qū)蔷€移動的“滑翔者”,滑翔者到了邊界成為不動的方塊。

更多有趣的圖形結(jié)構(gòu)有待發(fā)現(xiàn),用代碼來輔助這項工作還是比較方便的.....

代碼實現(xiàn)

用tkinter庫實現(xiàn)了軟件界面,畫布、按鈕、標簽等控件都是配角,全是為表現(xiàn)生命繁殖演化的核心代碼類方法 Lifes.reproduce() 作幫手的,源代碼lifegame.pyw如下:

from tkinter import messagebox as msgbox
import tkinter as tk
import webbrowser
import random
 
class Lifes:
    def __init__(self, rows=38, cols=38):
        self.row = rows
        self.col = cols
        self.items = [[0]*self.col for _ in range(self.row)]
        self.histroy = []
        self.histroySize = 30
        self.running = False
        self.runningSpeed = 100
        
    def rndinit(self, rate=0.1):
        self.histroy = []
        for i in range(self.row):
            for j in range(self.col):
                rnd = random.random()
                if rnd > 1-rate:
                    self.items[i][j]=1
 
    def reproduce(self):
        new = [[0]*self.col for _ in range(self.row)]
        self.add_histroy()
        if len(self.histroy) > self.histroySize:
            self.histroy.pop(0)
        for i in range(self.row):
            for j in range(self.col):
                if i*j==0 or i==self.row-1 or j==self.col-1:
                    new[i][j]=0
                else:
                    lifes=0
                    for m in range(i-1,i+2):
                        for n in range(j-1,j+2):
                            if m==i and n==j:
                                continue
                            lifes += self.items[m][n]
                    if self.items[i][j]:
                        if lifes==2 or lifes==3:
                            new[i][j]=1
                        else:
                            new[i][j]=0
                    else:
                        if lifes==3:
                            new[i][j]=1
        for idx,narray in enumerate(new):
            self.items[idx] = narray
 
    def is_stable(self):
        if len(self.histroy)<self.histroySize:
            return False
        arr = []
        for i in self.histroy:
            if i not in arr:
                arr.append(i)
        if len(arr)<10:
            return True
 
    def add_histroy(self, Items=None):
        arr = []
        if Items==None:
            Items=self.items[:]
        for item in Items:
            b = 0
            for i,n in enumerate(item[::-1]):
                b += n*2**i
            arr.append(b)
        self.histroy.append(arr)
 
 
def drawCanvas():
    global tv,rect
    tv = tk.Canvas(win, width=win.winfo_width(), height=win.winfo_height())
    tv.pack(side = "top")
    for i in range(36):
        coord = 40, 40, 760, i*20 + 40
        tv.create_rectangle(coord)
        coord = 40, 40, i*20 + 40, 760
        tv.create_rectangle(coord)
    coord = 38, 38, 760, 760
    tv.create_rectangle(coord,width=2)
    coord = 39, 39, 760, 760
    tv.create_rectangle(coord,width=2)
    coord = 38, 38, 762, 762
    tv.create_rectangle(coord,width=2)
    R,XY = 8,[50+i*20 for i in range(36)]
    rect = [[0]*36 for _ in range(36)]
    for i,x in enumerate(XY):
        for j,y in enumerate(XY):
            rect[i][j] = tv.create_rectangle(x-R,y-R,x+R,y+R,tags=('imgButton1'))
            tv.itemconfig(rect[i][j],fill='lightgray',outline='lightgray')
    tv.tag_bind('imgButton1','<Button-1>',on_Click)
 
def drawLifes():
    R,XY = 8,[50+i*20 for i in range(36)]
    if Life.running:
        for i,x in enumerate(XY):
            for j,y in enumerate(XY):
                if Life.items[i+1][j+1]:
                    tv.itemconfig(rect[i][j],fill='green',outline='green')
                else:
                    tv.itemconfig(rect[i][j],fill='lightgray',outline='lightgray')
        tv.update()
        Life.reproduce()
        if Life.is_stable():
            Life.running = False
            if sum(sum(Life.items,[])):
                msgbox.showinfo('Message','生命繁殖與湮滅進入穩(wěn)定狀態(tài)?。?!')
            else:
                msgbox.showinfo('Message','生命全部湮滅,進入死亡狀態(tài)?。?!')
    win.after(Life.runningSpeed, drawLifes)
 
def StartLife():
    if sum(sum(Life.items,[])):
        Life.histroy = []
        Life.running = True
    else:
        msgbox.showinfo('Message','請點擊小方塊填入生命細胞,或者使用隨機功能!')
 
def BreakLife():
    Life.running = not Life.running
    if Life.running:
        Life.histroy.clear()
        Life.add_histroy()
 
def RandomLife():
    Life.rndinit()
    Life.running = True
 
def ClearLife():
    Life.running = False
    Life.histroy = []
    Life.items = [[0]*38 for _ in range(38)]
    for x in range(36):
        for y in range(36):
            tv.itemconfig(rect[x][y],fill='lightgray',outline='lightgray')
 
def on_Enter(event):
    tCanvas.itemconfig(tVisit, fill='magenta')
 
def on_Leave(event):
    tCanvas.itemconfig(tVisit, fill='blue')
 
def on_Release(event):
    url = 'https://blog.csdn.net/boysoft2002?type=blog'
    webbrowser.open(url, new=0, autoraise=True)
 
def on_Click(event):
    x,y = (event.x-40)//20,(event.y-40)//20
    if not Life.running:
        if Life.items[x+1][y+1]:
            tv.itemconfig(rect[x][y],fill='lightgray',outline='lightgray')
        else:
            tv.itemconfig(rect[x][y],fill='red',outline='red')
        Life.items[x+1][y+1] = not Life.items[x+1][y+1]
 
def on_Close():
    if msgbox.askokcancel("Quit","Do you want to quit?"):
        Life.running = False
        print(Copyright())
        win.destroy()
 
def Introduce():
    txt = '''【生命游戲】\n\n生存定律:
    (1)當前細胞為湮滅狀態(tài)時,當周圍有3個存活細胞時,則迭代后該細胞變成存活狀態(tài)(模擬繁殖)。
    (2)當前細胞為存活狀態(tài)時,當周圍的鄰居細胞少于2個存活時,該細胞變成湮滅狀態(tài)(數(shù)量稀少)。
    (3)當前細胞為存活狀態(tài)時,當周圍有3個以上的存活細胞時,該細胞變成湮滅狀態(tài)(數(shù)量過多)。
    (4)當前細胞為存活狀態(tài)時,當周圍有2個或3個存活細胞時,該細胞保持原樣。'''
    return txt
 
def Copyright():
    return 'Lifes Game Ver1.0\nWritten by HannYang, 2022/08/01.'
 
 
if __name__ == '__main__':
 
    win = tk.Tk()
    X,Y = win.maxsize()
    W,H = 1024,800
    winPos = f'{W}x{H}+{(X-W)//2}+{(Y-H)//2}'
    win.geometry(winPos)
    win.resizable(False, False)
    win.title('生命游戲 Ver1.0')
    win.update()
    drawCanvas()
    Life = Lifes()
    drawLifes()
 
    tLabel = tk.Label(win, width=30, height=20, background='lightgray')
    tLabel.place(x=780, y=38)
    tLabel.config(text='\n\n\n'.join((Introduce(),Copyright())))
    tLabel.config(justify=tk.LEFT,anchor="nw",borderwidth=10,wraplength=210)
 
    bX,bY,dY = 835, 458, 50
    tButton0 = tk.Button(win, text=u'開始', command=StartLife)
    tButton0.place(x=bX, y=bY+dY*0 ,width=120,height=40)     
    tButton1 = tk.Button(win, text=u'暫停', command=BreakLife)
    tButton1.place(x=bX, y=bY+dY*1 ,width=120,height=40) 
    tButton2 = tk.Button(win, text=u'隨機', command=RandomLife)
    tButton2.place(x=bX, y=bY+dY*2 ,width=120,height=40)
    tButton3 = tk.Button(win, text=u'清空', command=ClearLife)
    tButton3.place(x=bX, y=bY+dY*3 ,width=120,height=40)
 
    tCanvas = tk.Canvas(win, width=200, height=45)
    tCanvas.place(x=800,y=716)
    tVisit = tCanvas.create_text((88, 22), text=u"點此訪問Hann's CSDN主頁!")
    tCanvas.itemconfig(tVisit, fill='blue', tags=('btnText'))
    tCanvas.tag_bind('btnText','<Enter>',on_Enter)
    tCanvas.tag_bind('btnText','<Leave>',on_Leave)
    tCanvas.tag_bind('btnText','<ButtonRelease-1>',on_Release)
    win.protocol("WM_DELETE_WINDOW", on_Close)
    win.mainloop()

編譯命令

D:\> pyinstaller -F lifegame.pyw --noconsole

運行界面

使用簡介

在生存空間里點擊方格種植細胞(甚至可以畫出你要表達的圖形),然后點擊開始;點下暫停鍵,則可以任意編輯生命圖形,再點開始繼續(xù)運行;點隨機鍵則由軟件隨機生成細胞位置;清空鍵可以在任何時候清空生存空間,進入暫停編輯狀態(tài)。 

后續(xù)改進

Lifes類預(yù)留了histroy屬性,后續(xù)可以增加回退功能;代碼缺點是生存空間的行列被我寫死了,以后版本中可以改進成任意定義行列數(shù);另一個缺點是對穩(wěn)定狀態(tài)的判斷比較簡單,之后可以增加計算變化周期的功能。

優(yōu)點就是可以任意編輯你的圖形,最后以一張自己的網(wǎng)名畫的圖作收尾:

前部分介紹性文字來源于百度百科等網(wǎng)絡(luò)資源 

以上就是Python實現(xiàn)生命游戲的示例代碼(tkinter版)的詳細內(nèi)容,更多關(guān)于Python 生命游戲的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評論

增城市| 海南省| 革吉县| 伊金霍洛旗| 吉木乃县| 涞水县| 竹溪县| 冕宁县| 邯郸市| 自贡市| 花莲县| 纳雍县| 高淳县| 和田县| 陵川县| 郧西县| 新绛县| 左云县| 洪江市| 怀宁县| 上犹县| 阳泉市| 山东省| 平阳县| 正定县| 鄂托克旗| 巫山县| 琼中| 海淀区| 平度市| 思南县| 闽清县| 青神县| 丰顺县| 开原市| 札达县| 九台市| 和林格尔县| 岐山县| 固原市| 泊头市|