生命游戏程序--Conway's Game of Life,它的发展由其初始状态决定,不需要进一步的输入。通过创建初始配置并观察其演变,它可以与生命游戏互动。
游戏的原始文档:https://en.wikipedia.org/wiki/The_Game_of_Life,有兴趣的可以去看下。
生命游戏
游戏大概的逻辑是这样的:
用一个二维表格表示“生存空间”,空间的每个方格中都可放置一个生命细胞,每个生命细胞只有两种状态:“生”或“死”。用绿色方格表示该细胞为“生”,空格(白色)表示该细胞为“死”。或者说方格网中绿色部分表示某个时候某种“生命”的分布图。生命游戏想要模拟的是:随着时间的流逝,这个分布图将如何一代一代地变化。进入死亡状态,称它“湮灭”状态。
下面就开始绘制和写细胞的衍生和死亡逻辑:
生命类:
、、、
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 reset_life(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_history()
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_history(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 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.derive_life()
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 reset_life(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_history()
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_history(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')
、、、
运行游戏:
、、、
if name == 'main':
win = tk.Tk()
X, Y = win.maxsize()
W, H = 1024, 800
winPos = f'{W}x{H}+{0}+{(Y - H) // 2}'
win.geometry(winPos)
win.resizable(True, True)
win.title('生命游戏')
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=(game_rule()))
tLabel.config(justify=tk.LEFT, anchor="nw", borderwidth=10, wraplength=210)
bX, bY, dY = 835, 458, 50
tButton0 = tk.Button(win, text=u'开始', command=start_life)
tButton0.place(x=bX, y=bY + dY * 0, width=120, height=40)
tButton1 = tk.Button(win, text=u'暂停', command=pause_game)
tButton1.place(x=bX, y=bY + dY * 1, width=120, height=40)
tButton2 = tk.Button(win, text=u'随机', command=random_life)
tButton2.place(x=bX, y=bY + dY * 2, width=120, height=40)
tButton3 = tk.Button(win, text=u'清空', command=clear_life)
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)
win.protocol("WM_DELETE_WINDOW", quit)
win.mainloop()
、、、
一场生命的起源,衍生,到湮灭,经历多长时间,最后生命是战胜困难赢得了生存还是被环境所覆灭。让它慢慢进行吧。
需要游戏素材,和完整代码,公众号大嗨无量回复:生命游戏 即可获取,长期有效。
今天的分享就到这里,希望感兴趣的同学关注我,每天都有新内容,不限题材,不限内容,你有想要分享的内容,也可以私聊我!
如果你想要跟大家分享你的文章,欢迎投稿~