文章目录
- 生命游戏(Game of Life)
- 游戏概述
- 生存定律
- 图形结构
- 代码实现
- 运行界面
- 使用简介
- 后续改进
- 关于Python技术储备
- 一、Python所有方向的学习路线
- 二、Python基础学习视频
- 三、精品Python学习书籍
- 四、Python工具包+项目源码合集
- ①Python工具包
- ②Python实战案例
- ③Python小游戏源码
- 五、面试资料
- 六、Python兼职渠道
生命游戏(Game of Life)
由剑桥大学约翰·何顿·康威设计的计算机程序。美国趣味数学大师马丁·加德纳(Martin Gardner,1914-2010)通过《科学美国人》杂志,将康威的生命游戏介绍给学术界之外的广大渎者,一时吸引了各行各业一大批人的兴趣,这时细胞自动机课题才吸引了科学家的注意。
游戏概述
用一个二维表格表示“生存空间”,空间的每个方格中都可放置一个生命细胞,每个生命细胞只有两种状态:“生”或“死”。用绿色方格表示该细胞为“生”,空格(白色)表示该细胞为“死”。或者说方格网中绿色部分表示某个时候某种“生命”的分布图。生命游戏想要模拟的是:随着时间的流逝,这个分布图将如何一代一代地变化。死亡太沉重,我想称它为“湮灭”状态。
生存定律
生存空间的每个方格都存在一个细胞,它的周边紧邻的8个方格上的称为邻居细胞。
(1)当前细胞为湮灭状态时,当周围有3个存活细胞时,则迭代后该细胞变成存活状态(模拟繁殖)。
(2)当前细胞为存活状态时,当周围的邻居细胞少于2个存活时,该细胞变成湮灭状态(数量稀少)。
(3)当前细胞为存活状态时,当周围有3个以上的存活细胞时,该细胞变成湮灭状态(数量过多)。
(4)当前细胞为存活状态时,当周围有2个或3个存活细胞时,该细胞保持原样。
简单来说,活细胞Cell看作是‘1’,死Cell看作‘0’,8个邻居的累加和Sum决定了下一轮的状态:
“繁殖”:死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。
生存空间中生命的繁殖和湮灭,如下图所示:
图形结构
在游戏进行中,杂乱无序的细胞会逐渐演化出各种精致、有形的图形结构;这些结构往往有很好的对称性,而且每一代都在变化形状。一些形状一经锁定就不会逐代变化。有时,一些已经成形的结构会因为一些无序细胞的“入侵”而被破坏。但是形状和秩序经常能从杂乱中产生出来。
通常会有以下四种状态:
不动点(fixed points):变化终结于恒定图像
交替态(alternation):图像出现周期性变化
随机态(randomness):图像变化近乎随机
复杂态(complexity):图像存在某种复杂规律
常见的不动结构:
周期变化的结构:
逐步趋向湮灭的结构:
由一根10个连续细胞演化出来的周期结构:
动态变化后全部湮灭的结构:
移动的飞船:周期变化且逐渐向右平移
飞船到了边界变成向对角线移动的“滑翔者”,滑翔者到了边界成为不动的方块。
更多有趣的图形结构有待发现,用代码来辅助这项工作还是比较方便的…
代码实现
用tkinter库实现了软件界面,画布、按钮、标签等控件都是配角,全是为表现生命繁殖演化的核心代码类方法 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','生命繁殖与湮灭进入稳定状态!!!')
else:
msgbox.showinfo('Message','生命全部湮灭,进入死亡状态!!!')
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)当前细胞为湮灭状态时,当周围有3个存活细胞时,则迭代后该细胞变成存活状态(模拟繁殖)。
(2)当前细胞为存活状态时,当周围的邻居细胞少于2个存活时,该细胞变成湮灭状态(数量稀少)。
(3)当前细胞为存活状态时,当周围有3个以上的存活细胞时,该细胞变成湮灭状态(数量过多)。
(4)当前细胞为存活状态时,当周围有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
运行界面
使用简介
在生存空间里点击方格种植细胞(甚至可以画出你要表达的图形),然后点击开始;点下暂停键,则可以任意编辑生命图形,再点开始继续运行;点随机键则由软件随机生成细胞位置;清空键可以在任何时候清空生存空间,进入暂停编辑状态。
后续改进
Lifes类预留了histroy属性,后续可以增加回退功能;代码缺点是生存空间的行列被我写死了,以后版本中可以改进成任意定义行列数;另一个缺点是对稳定状态的判断比较简单,之后可以增加计算变化周期的功能。
优点就是可以任意编辑你的图形,最后以一张自己的网名画的图作收尾:
前部分介绍性文字来源于百度百科等网络资源
关于Python技术储备
学好 Python 不论是就业还是做副业赚钱都不错,但要学会 Python 还是要有一个学习规划。最后大家分享一份全套的 Python 学习资料,给那些想学习 Python 的小伙伴们一点帮助!
微信扫描下方CSDN官方认证二维码免费领取【保证100%免费
】
一、Python所有方向的学习路线
Python所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。
二、Python基础学习视频
② 路线对应学习视频
还有很多适合0基础入门的学习视频,有了这些视频,轻轻松松上手Python~在这里插入图片描述
③练习题
每节视频课后,都有对应的练习题哦,可以检验学习成果哈哈!
因篇幅有限,仅展示部分资料
三、精品Python学习书籍
当我学到一定基础,有自己的理解能力的时候,会去阅读一些前辈整理的书籍或者手写的笔记资料,这些笔记详细记载了他们对一些技术点的理解,这些理解是比较独到,可以学到不一样的思路。
四、Python工具包+项目源码合集
①Python工具包
学习Python常用的开发软件都在这里了!每个都有详细的安装教程,保证你可以安装成功哦!
②Python实战案例
光学理论是没用的,要学会跟着一起敲代码,动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。100+实战案例源码等你来拿!
③Python小游戏源码
如果觉得上面的实战案例有点枯燥,可以试试自己用Python编写小游戏,让你的学习过程中增添一点趣味!
五、面试资料
我们学习Python必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有阿里大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。
六、Python兼职渠道
而且学会Python以后,还可以在各大兼职平台接单赚钱,各种兼职渠道+兼职注意事项+如何和客户沟通,我都整理成文档了。
这份完整版的Python全套学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费
】