如何在Python中迭代或处理网格或坐标

1 投票
1 回答
2130 浏览
提问于 2025-04-18 03:23

我创建了一个 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' 文件的图:

enter image description here

在上面的图中,可以明显看到火焰只能向上扩散到一定程度,然后停止,留下了很多活着的树。

我只想要那些活着的树的坐标,并把它们画出来。

对于上面显示的特定输入图,最终剩下的活树的图应该是这样的:

enter image description here

部分被擦除的点是着火的,不应该出现在这里。

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()

forest

撰写回答