生活游戏邻居问题
Game of life neighbours issue
我正在尝试在 python 中创建我的 Game of life 代码,但是当它检查活着的邻居时,它似乎有问题。我已经尝试解决它 2 天了,但我仍然不知道我错过了什么。
这是分成几部分的代码。
from random import randrange
from tkinter import *
from time import sleep
root = Tk()
canv = Canvas(width = 800, height = 800)
canv.pack()
def value():
if randrange(16) == 0:
return 1
else:
return 0
我在 tkinter 中设置 canvas 并创建一个函数来确定细胞的状态,因此每个细胞都有 1/x 的机会首先存活。
def pprint(lst):
for row in lst:
print(row)
我在尝试调试时创建了一个漂亮的打印函数。
def nb(life,row,col):
count = 0
#print(x,y)
#print(life[x][y])
for r in [row-1, row, row+1]:
for c in [col-1,col,col+1]:
if life[r][c] == 1:
count += 1
if life[row][col] == 1:
count -= 1
#print(count,end=" ")
return count
这个函数应该return一个单元格拥有的存活邻居的数量。 (调试代码时留下的注释)
def ud(life,life2,size,box):
#print(life)
while True:
try:
for row in range(1,size+1):
for col in range(1,size+1):
#print(row,col)
a = nb(life,row,col)
print("[{0},{1}]".format(row,col), end =" ")
print(a, end=" ")
if ((1<a) and (a<4)):
life2[row][col] = 1
canv.itemconfig(box[row-1][col-1], fill ="black")
else:
life2[row][col] = 0
canv.itemconfig(box[row-1][col-1], fill ="white")
print("")
print("ok")
#print(life2[19][19])
root.update()
pprint(life)
#sleep(5)
life = life2
sleep(800/size**2)
print("")
except:
break
这是主要的更新功能。它应该 运行 life 二维数组中每个单元格的 nb 函数,并确定它在 life2 中的值。 “box”是一个二维数组,其中包含视觉网格上每个单元格的矩形 tkinter id。 (是的,打印功能也是为了调试。)
#######
size = 10
w = 10
box = [[canv.create_rectangle(y*w,x*w,y*w+10,x*w+10) for y in range(size)] for x in range(size)]
life = [[value() for y in range(size)] for x in range(size)]
life2 = [[0 for y in range(size+2)] for x in range(size+2)]
for i in range(1,size+1):
life2[i] = [0] + life[i-1] + [0]
#life = life2
pprint(life)
root.update()
ud(life2,life2,size,box)
del box
del life
del life2
我创建了盒子变量(w = 细胞的宽度)并生成了随机活细胞。然后我为“life”创建了一个“0”帧(这样程序在 nb 检查时不会在拐角处中断。而且我知道我可以使用 try/except)。然后我使用参数启动 ud 函数(大小 = 一行中的单元格数;两个生命矩阵参数都是 life2,因为理论上 2nd 将被完全重写)
那么程序有什么问题呢?
def ud(life,life2,size,box):
中的这一行 life = life2
使得 life
和 live2
都 name/point 到相同的数据。您需要 深度复制 life2
并让 life
指向绝对独立的数据。
深拷贝,因为你的life2
包含其他列表,如果你只浅拷贝 live = life2[:]
你仍然会遇到同样的问题 - live 将在其内部列出唯一的引用,但内部列表的引用指向的数据仍将共享。您使用 import copy
& copy.deepcopy(...)
进行深度复制。
重命名:
import copy
print()
a = [[1,3,5],[2,4,6]]
b = a # second name, same data
a[0] = [0,8,15] # replaces the ref on a[0] with a new one, b == a
a[1][2] = 99 # modifies a value inside the 2nd list ref, b == a
print (a,"=>",b) # b is just another name for a
输出:
# nothing got preserved, both identical as b ist just another name for a
([[0, 8, 15], [2, 4, 99]], '=>', [[0, 8, 15], [2, 4, 99]])
浅拷贝:
a = [[1,3,5],[2,4,6]]
b = a[:] # shallow copy
a[0] = [0,8,15] # replaces one ref with a new one (only in a)
a[1][2] = 99 # modifies the value inside 2nd list, same ref in a&b
print (a,"=>",b)
输出:
# b got "unique" refs to the inner lists, if we replace one in a
# this does not reflect in b as its ref is unique. chaning values
# inside a inner list, will be reflected, as they are not uniqe
([[0, 8, 15], [2, 4, 99]], '=>', [[1, 3, 5], [2, 4, 99]])
深拷贝:
a = [[1,3,5],[2,4,6]]
b = copy.deepcopy(a) # deep copy
a[0] = [0,8,15] # only a modified
a[1][2] = 99 # only in a modified
print (a,"=>",b)
输出:
# completely independent - b shares no refs with former a, all got new'ed up
([[0, 8, 15], [2, 4, 99]], '=>', [[1, 3, 5], [2, 4, 6]])
如果将上面的 print
替换为
print(id(a), id(a[0]), id(a[1]), id(b), id(b[0]), id(b[1]))
你得到了 a
的唯一 ID 的输出,它是 content 以及 b
和它的内容:
重命名:
`a`: 139873593089632, 139873593146976, 139873593072384
`b`: 139873593089632, 139873593146976, 139873593072384
浅:
`a`: 139873593229040, 139873593089632, 139873593146040
`b`: 139873593227168, 139873593088552, 139873593146040
深:
`a`: 139873593253968, 139873593227168, 139873593072384
`b`: 139873593229040, 139873593089632, 139873593254112
我正在尝试在 python 中创建我的 Game of life 代码,但是当它检查活着的邻居时,它似乎有问题。我已经尝试解决它 2 天了,但我仍然不知道我错过了什么。 这是分成几部分的代码。
from random import randrange
from tkinter import *
from time import sleep
root = Tk()
canv = Canvas(width = 800, height = 800)
canv.pack()
def value():
if randrange(16) == 0:
return 1
else:
return 0
我在 tkinter 中设置 canvas 并创建一个函数来确定细胞的状态,因此每个细胞都有 1/x 的机会首先存活。
def pprint(lst):
for row in lst:
print(row)
我在尝试调试时创建了一个漂亮的打印函数。
def nb(life,row,col):
count = 0
#print(x,y)
#print(life[x][y])
for r in [row-1, row, row+1]:
for c in [col-1,col,col+1]:
if life[r][c] == 1:
count += 1
if life[row][col] == 1:
count -= 1
#print(count,end=" ")
return count
这个函数应该return一个单元格拥有的存活邻居的数量。 (调试代码时留下的注释)
def ud(life,life2,size,box):
#print(life)
while True:
try:
for row in range(1,size+1):
for col in range(1,size+1):
#print(row,col)
a = nb(life,row,col)
print("[{0},{1}]".format(row,col), end =" ")
print(a, end=" ")
if ((1<a) and (a<4)):
life2[row][col] = 1
canv.itemconfig(box[row-1][col-1], fill ="black")
else:
life2[row][col] = 0
canv.itemconfig(box[row-1][col-1], fill ="white")
print("")
print("ok")
#print(life2[19][19])
root.update()
pprint(life)
#sleep(5)
life = life2
sleep(800/size**2)
print("")
except:
break
这是主要的更新功能。它应该 运行 life 二维数组中每个单元格的 nb 函数,并确定它在 life2 中的值。 “box”是一个二维数组,其中包含视觉网格上每个单元格的矩形 tkinter id。 (是的,打印功能也是为了调试。)
#######
size = 10
w = 10
box = [[canv.create_rectangle(y*w,x*w,y*w+10,x*w+10) for y in range(size)] for x in range(size)]
life = [[value() for y in range(size)] for x in range(size)]
life2 = [[0 for y in range(size+2)] for x in range(size+2)]
for i in range(1,size+1):
life2[i] = [0] + life[i-1] + [0]
#life = life2
pprint(life)
root.update()
ud(life2,life2,size,box)
del box
del life
del life2
我创建了盒子变量(w = 细胞的宽度)并生成了随机活细胞。然后我为“life”创建了一个“0”帧(这样程序在 nb 检查时不会在拐角处中断。而且我知道我可以使用 try/except)。然后我使用参数启动 ud 函数(大小 = 一行中的单元格数;两个生命矩阵参数都是 life2,因为理论上 2nd 将被完全重写)
那么程序有什么问题呢?
def ud(life,life2,size,box):
中的这一行 life = life2
使得 life
和 live2
都 name/point 到相同的数据。您需要 深度复制 life2
并让 life
指向绝对独立的数据。
深拷贝,因为你的life2
包含其他列表,如果你只浅拷贝 live = life2[:]
你仍然会遇到同样的问题 - live 将在其内部列出唯一的引用,但内部列表的引用指向的数据仍将共享。您使用 import copy
& copy.deepcopy(...)
进行深度复制。
重命名:
import copy
print()
a = [[1,3,5],[2,4,6]]
b = a # second name, same data
a[0] = [0,8,15] # replaces the ref on a[0] with a new one, b == a
a[1][2] = 99 # modifies a value inside the 2nd list ref, b == a
print (a,"=>",b) # b is just another name for a
输出:
# nothing got preserved, both identical as b ist just another name for a
([[0, 8, 15], [2, 4, 99]], '=>', [[0, 8, 15], [2, 4, 99]])
浅拷贝:
a = [[1,3,5],[2,4,6]]
b = a[:] # shallow copy
a[0] = [0,8,15] # replaces one ref with a new one (only in a)
a[1][2] = 99 # modifies the value inside 2nd list, same ref in a&b
print (a,"=>",b)
输出:
# b got "unique" refs to the inner lists, if we replace one in a
# this does not reflect in b as its ref is unique. chaning values
# inside a inner list, will be reflected, as they are not uniqe
([[0, 8, 15], [2, 4, 99]], '=>', [[1, 3, 5], [2, 4, 99]])
深拷贝:
a = [[1,3,5],[2,4,6]]
b = copy.deepcopy(a) # deep copy
a[0] = [0,8,15] # only a modified
a[1][2] = 99 # only in a modified
print (a,"=>",b)
输出:
# completely independent - b shares no refs with former a, all got new'ed up
([[0, 8, 15], [2, 4, 99]], '=>', [[1, 3, 5], [2, 4, 6]])
如果将上面的 print
替换为
print(id(a), id(a[0]), id(a[1]), id(b), id(b[0]), id(b[1]))
你得到了 a
的唯一 ID 的输出,它是 content 以及 b
和它的内容:
重命名:
`a`: 139873593089632, 139873593146976, 139873593072384
`b`: 139873593089632, 139873593146976, 139873593072384
浅:
`a`: 139873593229040, 139873593089632, 139873593146040
`b`: 139873593227168, 139873593088552, 139873593146040
深:
`a`: 139873593253968, 139873593227168, 139873593072384
`b`: 139873593229040, 139873593089632, 139873593254112