Python实现Game of Life(元胞自动机)
Game of Life规则说明
py代码实现了历史结果保存再用(txt文本储存)
# 再次运行时建议清理outpng文件夹
import numpy as np
from PIL import Image
# 矩阵处理
def juzhen(a,b):
i = 0
while i < x:
j = 0
while j < y:
num = a[i,j]
# 边界处理
if i == 0:
i1,i2 = 1,i
elif i == x - 1:
i1,i2 = i,i-1
else:
i1,i2 = i,i
if j == 0:
j1,j2 = 1,j
elif j == y - 1:
j1,j2 = j,j-1
else:
j1,j2 = j,j
# 求和
box = np.sum(a[i1-1:i2+2,j1-1:j2+2])
# 生死判断
if box - num < 2 or box - num > 3:
b[i,j] = 0
elif box - num == 3:
b[i,j] = 1
else:
b[i,j] = num
j += 1
i += 1
return(b)
# 绘图
def pic(b,x,y,box,m,num):
print("等待矩阵处理 Loading...")
im = Image.new("RGBA",(box*x,box*y),(0,0,0))
i = 0
while i < x:
j = 0
while j < y:
box_x = 0
while box_x < box:
box_y = 0
while box_y < box:
if b[i,j] == 1:
im.putpixel((i*box+box_x,j*box+box_y),(0,255,0))
box_y += 1
box_x += 1
j += 1
i += 1
m = (len(str(num))-len(str(m)))*'0'+str(m)
print("处理完成,输出life"+"%s"%m+".png\n")
im.save('outpng\life'+'%s'%m+'.png', 'png')
# ___________main___________
# 数组宽高
x,y = 100,100
# 图片放大倍数
box = 10
i = 0
a_num = input("输入(1.新建随机矩阵/2.读取history.txt)")
# 随机矩阵
if a_num == '1':
a = np.random.randint(2,size=(x,y))
# 读取上次运行的最后结果
elif a_num == '2':
f = open("history.txt","r")
s = f.read()
s2 = ""
for s1 in s:
if s1 == '0' or s1 == '1':
s2 += s1
s_box = int(len(s2)**0.5)
# 间接定义,防止产生二维数组引用的问题
# 例子说明:matrix = [array] * 3操作中,只是创建3个指向array的引用,所以一旦array改变,matrix中3个list也会随之改变。
# np的列表和py自带列表有区别,如py自带列表不支持二维切片,不能混用
a = np.random.randint(2,size=(s_box,s_box))
s3 = 0
while s3 < s_box:
s4 = 0
while s4 < s_box:
a[s3][s4] = s2[s3*s_box+s4]
s4 += 1
s3 += 1
num = int(input("输入处理次数:"))
b = np.array([[0]*x]*y)
print("\n原始矩阵")
print(a)
pic(a,x,y,box,i,num)
while i < num:
print("第%d个矩阵"%(i+1))
b = juzhen(a,b)
print(b)
i += 1
pic(b,x,y,box,i,num)
a = b
b = np.array([[0]*x]*y)
f = open("history.txt","w")
f.write(str(a.tolist()))
f.close()
print("处理完成\n图片输出到outpng,最后一次矩阵保存到history.txt")
遇到的问题主要还是二维矩阵,被坑的内容写在注释中了,引以为戒
Game of Life因为是输出图片,并没有进行大量的输出以展示元胞机自动的特点,有兴趣的小伙伴可以试一下
更新
将图片拼接成视频,以更直观的方式观看形态变化
import os
import cv2
path = r'outpng'
# 需要转为视频的图片的尺寸,必须所有图片大小一样,不然无法合并成功
size = (1000, 1000)
filelist = os.listdir(path)
filelist2 = [os.path.join(path, i) for i in filelist]
fps = 5 # 设定视频每秒5帧,可以自行修改
video = cv2.VideoWriter("生命游戏.avi", cv2.VideoWriter_fourcc('M', 'J', 'P', 'G'), fps,size)
print("图片提取中 Loading...\n")
for item in filelist2:
if item.endswith('.png'):
print(item)
img = cv2.imread(item)
video.write(img)
video.release()
cv2.destroyAllWindows()
print('\n视频合成生成完成')