如何在Python中迭代或处理网格或坐标
我创建了一个 N x N 的网格森林,里面有随机数量的树。为了种树,我在每个格子里随机选择一个数字,然后把种下树的坐标分别存储在一个列表 li[]
(表示 x 轴)和 lj[]
(表示 y 轴)中。同时,我还把这些坐标放进了一个 .dat 文件里。
在 Python 中,我的代码是:
from math import *
from random import random
n = input('Choose grid, N = ')
p = 0.5
li = []
lj = []
fid = open('plant.dat','w')
for i in range(1,n+1):
for j in range(1,n+1):
x = random()
if x<p:
li.append(i)
lj.append(j)
print>>fid,i,j
print (i,j),'is',1
else:
print (i,j),'is',0
print (i,j)
print (p,x,n),'and',n*n*p,li,lj
现在我想让这些树着火。我从最底下的点开始点火,然后火会向四个方向扩散到相邻的树木(不包括对角线方向)。
为此,我检查 y 轴的值是否为 1,这代表底部的点,然后把这个点标记为着火。
接下来,我需要把火向相邻的树(不包括对角线方向)扩散:
在这里我遇到了困难,不知道该怎么做。基本上,我想从底部的着火点开始,增加 x 轴和 y 轴的值,然后检查相邻的点。但现在只显示了底部的那一行。
这是我的代码:
print 'Now we are firing'
lif=[]
ljf=[]
fid1 = open('fire.dat','w')
for b in range(len(lj)):
if lj[b] == 1:
print 'We fire here',(li[b],lj[b])
print>>fid1,li[b],lj[b]
lif.append(li[b])
ljf.append(lj[b])
#for e in range(2,n+1):
for r in li:
if li[r] == li:
print 'fire spread at',(li[r],lj[r])
print >> fid1,li[r],lj[r]
lif.append(li[r])
ljf.append(lj[r])
这是我用 gnuplot 生成的 'plant.dat' 文件的图:

在上面的图中,可以明显看到火焰只能向上扩散到一定程度,然后停止,留下了很多活着的树。
我只想要那些活着的树的坐标,并把它们画出来。
对于上面显示的特定输入图,最终剩下的活树的图应该是这样的:
部分被擦除的点是着火的,不应该出现在这里。
1 个回答
2
这是一个很好的例子,说明递归函数如何能让复杂的问题变得相对简单。不过首先,我想用numpy矩阵来表示你的问题,而不是用索引向量,同时尽量保持你的代码不变。下面是你的第二段代码,我用0.5表示树木,用1表示火灾,来表示整个森林。
print 'Now we are firing'
lif=[]
ljf=[]
fid1 = open('fire.dat','w')
for b in range(len(lj)):
if lj[b] == 1:
print 'We fire here',(li[b],lj[b])
print>>fid1,li[b],lj[b]
lif.append(li[b])
ljf.append(lj[b])
import numpy as np
forest_mat = np.zeros([n,n])
coords = zip(li,lj)
for coord in coords:
forest_mat[coord[0]-1,coord[1]-1] = 0.5
coords = zip(lif,ljf)
for coord in coords:
forest_mat[coord[0]-1,coord[1]-1] = 1
forest_mat = np.flipud(forest_mat.transpose())
接下来,我会定义一个叫做fire_trees的函数,它会递归地点燃相邻的树木,把它们的值设为1。我们会对第一行的每棵树这样做,因为那些树之前已经着火了。
def fire_trees(matrix,ij):
if ((0 <= ij[0]) and (ij[0] < len(matrix)) and (0 <= ij[1]) and (ij[1] < len(matrix)))==False:
print "out of bounds"
return matrix
if matrix[ij[0],ij[1]]==0.5:
print "Fire this tree:", ij[0],ij[1]
matrix[ij[0],ij[1]] = 1
matrix = fire_trees(matrix,(ij[0]-1,ij[1]))
matrix = fire_trees(matrix,(ij[0]+1,ij[1]))
matrix = fire_trees(matrix,(ij[0],ij[1]-1))
matrix = fire_trees(matrix,(ij[0],ij[1]+1))
print "No more trees to fire."
return matrix
for i,j in enumerate(forest_mat[n-1,]):
if j==1:
#fire adjacent trees
forest_mat = fire_trees(forest_mat,(n-2,i))
我没有使用gnuplot,而是用matplotlib的matshow函数,具体如下:
import matplotlib.pyplot as plt
image = forest_mat
row_labels = range(n)
plt.matshow(image)
plt.show()