我只是在写一个生命游戏脚本,看来我从来没有真正做到过。我创建了一个矩阵数组,其中包含列的子数组,每个列包含该列中每行的值。当我循环检查邻居时,我想像下面那样计算它们:
var count = 0;
count += this.data[i-1][j-1];
count += this.data[i-1][i];
count += this.data[i-1][j+1];
count += this.data[i][j-1];
count += this.data[i][j+1];
count += this.data[i+1][j-1];
count += this.data[i+1][i];
count += this.data[i+1][j+1];
显然,在i-1
和i+1
索引上会导致数组的开头和结尾出现问题。我可以检查行的值(最深的值)的未定义,如下所示:
count += typeof this.data[i-1][j-1] !== 'undefined' ? this.data[i-1][j-1] : 0;
但是如果列数组未定义,显然会出错,我无法再写几行来检查它。无论如何,我可以在这一行中捕获此错误,或者是否有更快的方法来获取此数据。我只是不想要大量的尝试/捕获或if / elses来解释矩阵的边缘?
我知道我可以移除子数组结构并且只有一个长数据库但我只是对处理这种结构的有效方法感到好奇。
答案 0 :(得分:2)
“最干净”是一个主观术语,但有三种可能性:
使用JavaScript的curiously powerful ||
operator:
count += (this.data[i-1] || [])[j-1] || 0;
这有两个原因:
在JavaScript中,访问不存在的数组索引会返回undefined
。它不会导致错误。
与许多编程语言不同,JavaScript的||
返回其第一个操作数,如果该操作数是真实的,则返回其第二个操作数,而不是布尔值。 Truthy值是非虚假的值;假名值为0
,undefined
,null
,""
,NaN
,当然还有false
。因此1 || 0
为1
,undefined || 0
为0
,0 || 0
也为0
。
请注意,|| []
部分除非this.data[i-1]
部分为undefined
,否则不会创建数组。但如果您担心创建这样的临时数组,您可以在整个脚本中定义一个(var blank = [];
),然后使用它:
count += (this.data[i-1] || blank)[j-1] || 0;
定义您的数组(“垂直”数组和所有“水平”数组)两个元素太大,并将边缘周围的值设置为0.然后从1
循环到{{1你不必担心超出范围,因为< length - 1
案例会将你带到第0个元素,它具有值-1
和0
个案例将带您进入+1
元素,该元素的值为length-1
。这提供了非常干净的代码,代价是一点点额外的内存。或者:
有一个函数来获取检查坐标的值,如果其中一个无效,则返回0
。这提供了非常干净的代码,代价是增加了一小部分开销。