[英]Conway's game of life: How to initialize the grid?
我正在尝试编写一个函数nextGen
,该函数接受单个参数(当前网格),然后计算但不打印新网格。 基本上,我不确定如何执行检查位,它会检查周围的9个单元格。 首先,我以为我可以创建一个完全由0构成的基本网格,该网格比当前网格大2行2列,因此它是0的边界,但是我不知道如何获取初始网格的值进入基础网格。 我当前的代码是:
def initlist(positions,initval):
newlist = []
for i in range(0,positions):
newlist.append(initval)
return newlist
def init2DTableV3(rows,cols,initval):
newrow = initlist(cols,initval)
table = initlist(rows,newrow)
return table
def nextGen(current_grid):
rows = len(current_grid)
cols = len(current_grid[0])
base_value = 0
base_grid = init2DTableV3(rows + 2, cols + 2, base_value)
import copy
init_newgrid = copy.deepcopy(current_grid)
有人可以帮我吗? 我是Python的初学者,所以如果有人可以解释如何使用基本的Python函数来制作nextGen
,那就太好了。
如果我理解正确,则说明您具有基本网格,并且不确定如何在边缘上填充零,对吗?
有时,首先考虑一维问题比较容易,然后查看是否有可能将其扩展到2D。 假设您的1D网格看起来像
1 0 0 1 0 0 0 0 1 0 1
然后,如果您想在数组的两端都填充零,则它看起来像
0 1 0 0 1 0 0 0 0 1 0 1 0
假设您只是使用标准的Python列表,这很容易做到。 您可以简单地使用list.insert()
插入开头,并使用.insert()
或.append()
插入结尾。
>>> L = [1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1]
>>> L.insert(0,0)
>>> L.append(0)
>>> L
[0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0]
因此,让我们用2D列表尝试相同的事情,看看会发生什么:
>>> M = [[1,1],[1,1]]
>>> M.insert(0,[0,0])
>>> M.append([0,0])
>>> M
[[0, 0], [1, 1], [1, 1], [0, 0]]
因此,这在顶部和底部给出了一个带有零的行,但是我们没有左侧和右侧。 我们将在稍后处理。 当我添加顶行和底行时,我明确为其指定了所需的零个数(即[0,0]
)。 但是您可以轻松地自动执行此操作,只需使用一行的长度即可:
>>> M = [[1,1],[1,1]]
>>> M.insert(0,[0]*len(M[0]))
>>> M.append([0]*len(M[0]))
>>> M
[[0, 0], [1, 1], [1, 1], [0, 0]]
现在,每个行向量的长度仅为2,但应为4。一个简单而明确的方法是遍历子列表并插入并附加0:
>>> for r in M:
... r.insert(0,0)
... r.append(0)
...
>>> M
[[0, 0, 0, 0], [0, 1, 1, 0], [0, 1, 1, 0], [0, 0, 0, 0]]
这将为您提供填充的2D列表。
但是总的来说,我建议对这些任务使用numpy
,因为您可以简单地在2D numpy
数组上使用numpy.pad()
作为启动器,但是更复杂的操作也将更快,并且数组更易于索引等。
另一种方法是使用已经存在的内容,而不是添加额外的元素。
我最近用javascript写了Life的副本,但是想法是一样的。 每个单元格均由其坐标标识,并使用其邻居坐标的对象(Python:字典)进行初始化。
makeCell(x, y) {
let div = $('<div></div>');
let id = "x" + x + "y" + y;
let neighbors = this.getNeighbors(x, y);
let attributes = {
"id": id,
"data-entity": _entity.id
}
$("#grid").append(div);
}
function getNeighbors(x, y) {
let leftX = x - 1;
let rightX = x + 1;
let topY = y - 1;
let bottomY = y + 1;
// neighbor positions
let neighbors = [
"#x" + leftX + "y" + topY,
"#x" + x + "y" + topY,
"#x" + rightX + "y" + topY,
"#x" + leftX + "y" + y,
"#x" + rightX + "y" + y,
"#x" + leftX + "y" + bottomY,
"#x" + x + "y" + bottomY,
"#x" + rightX + "y" + bottomY,
];
return neighbors;
}
在该回合结束时,所有活细胞都存储在列表中。 检查每个活细胞及其每个邻居,以计算其各自的活邻居细胞。
this.cellCountNeighbors = function() {
let count = 0;
let neighbors = this.neighbors;
let n = this.entity;
let u = this;
neighbors.forEach(function(neighbor) {
let div = $(neighbor);
if ($(div).hasClass("alive")) {
count++;
} else if (!check_cells.includes(neighbor)) {
check_cells.push(neighbor);
}
});
return count;
}
以及生活检查条件:
this.setNextLife = function(_count) {
if (this.alive) {
if (_count == 2 || _count == 3) {
return this.age++;
} else {
changes.push(this);
return;
}
} else {
changes.push(this);
}
}
其中changes
是小区的名单被切换bool
活着/死亡。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.