我知道递归的现实例子并不多。我想我今天找到了一个并且我想分享Q& A风格,因为我觉得它非常吸引人。
我使用Phaser引擎进行我的游戏。用户点击后,我需要找到用户点击的游戏元素。一旦多个元素一个在另一个之上,这就变得复杂。然后,我需要检查它们的渲染顺序并选择具有最高元素的元素。
在Phaser中,所有显示对象的根都是" world"。所有现有元素都是世界上的直接子女或儿童的子女。它是游戏世界的顶级分支结构。孩子们按照渲染顺序排序,这意味着最后一个在顶部。
这是一个例子,让每个显示对象用数字表示:
var world = [
[
18,
3,
[
1,
14,
2
],
5,
9,
[
3,
5
]
],
[
16,
7
]
];
此阵列中有三个级别,有两个主要"组"。在游戏术语中,第二组在第一组之后添加,因此它呈现在顶部。在第一个组内,最后一个元素呈现在顶部,这是一个组。在该组内部,最后一个元素再次呈现在顶部,依此类推。在所有这些元素中,最顶层渲染的元素是7
,因为它是最后一个元素。
我们说我点击了鼠标,它恰好位于数字大于10(18
,14
和16
)所代表的所有元素之上。我需要的是16
,因为它是最远的。
我如何得到它?
答案 0 :(得分:1)
您可以使用递归方法Array#forEach
。
function getValue(array, cb) {
var last;
array.forEach(function iter(a) {
if (Array.isArray(a)) {
a.forEach(iter);
return;
}
if (cb(a)) {
last = a;
}
});
return last;
}
function check(v) {
return v > 10;
}
var world = [[18, 3, [1, 14, 2], 5, 9, [3, 5]], [16, 7]];
console.log(getValue(world, check));

带有Array#reduce
的版本以及回调的闭包。
function getLastValue(cb) {
return function iter(r, a) {
return Array.isArray(a) ? a.reduce(iter, r) : cb(a) ? a : r;
};
}
function greaterThan10(v) {
return v > 10;
}
var world = [[18, 3, [1, 14, 2], 5, 9, [3, 5]], [16, 7]];
console.log(world.reduce(getLastValue(greaterThan10), null));

附录受到4castle answer的启发,从后面迭代,并在第一次找到时提前返回。
function getValue(array, cb) {
var i = array.length, r;
while (i--) {
if (Array.isArray(array[i])) {
r = getValue(array[i], cb);
if (r !== undefined) {
return r;
}
}
if (cb(array[i])) {
return array[i];
}
};
}
function check(v) {
return v > 10 && v < 16;
}
var world = [[18, 3, [1, 14, 2], 5, 9, [3, 5]], [16, 7]];
console.log(getValue(world, check)); // 14
&#13;
答案 1 :(得分:1)
要获得满足某些条件的多维数组的最后一个元素,您应该使用某种检查来确保元素是否为数组,以便您知道是否进行递归调用。可以使用Array.isArray
查找某些内容是否为数组,或者您可以使用duck-typing并检查length
属性。
在数组上向后循环将帮助您更快地找到顶部元素。
function topElement(condition, array) {
for (var i = array.length - 1; i >= 0; i--) {
var val = array[i];
if (Array.isArray(val)) {
var top = topElement(condition, val);
if (top !== undefined) {
return top;
}
} else if (condition(val)) {
return val;
}
}
return undefined;
}
function check(num) {
return num > 10;
}
var world = [[18, 3, [1, 14, 2], 5, 9, [3, 5]], [16, 7]];
console.log(topElement(check, world));
&#13;
答案 2 :(得分:0)
function topElement(fn, object, data) {
if (fn(object) === true) {
data = object;
}
for (var i = 0; i < object.length; i++) {
data = topElement(fn, object[i], data);
}
return data;
}
function check(num) {
return (num > 10);
}
topElement(check, world); // 16
如果我想要一个不同的条件,我只想改变check()
方法。在我的游戏中,不同的条件是用户点击的位置。 check()
将游戏元素与点进行比较,如果它在其中,则返回true
,然后topElement()
返回符合条件的渲染顺序最远的元素。
这是fiddle。