通过递归

时间:2017-01-11 21:21:21

标签: javascript arrays recursion rendering

我知道递归的现实例子并不多。我想我今天找到了一个并且我想分享Q& A风格,因为我觉得它非常吸引人。

我使用Phaser引擎进行我的游戏。用户点击后,我需要找到用户点击的游戏元素。一旦多个元素一个在另一个之上,这就变得复杂。然后,我需要检查它们的渲染顺序并选择具有最高元素的元素。

在Phaser中,所有显示对象的根都是" world"。所有现有元素都是世界上的直接子女或儿童的子女。它是游戏世界的顶级分支结构。孩子们按照渲染顺序排序,这意味着最后一个在顶部。

这是一个例子,让每个显示对象用数字表示:

var world = [
    [
        18,
        3,
        [
            1,
            14,
            2
        ],
        5,
        9,
        [
            3,
            5
        ]
    ],
    [
        16,
        7
    ]
];

此阵列中有三个级别,有两个主要"组"。在游戏术语中,第二组在第一组之后添加,因此它呈现在顶部。在第一个组内,最后一个元素呈现在顶部,这是一个组。在该组内部,最后一个元素再次呈现在顶部,依此类推。在所有这些元素中,最顶层渲染的元素是7,因为它是最后一个元素。

我们说我点击了鼠标,它恰好位于数字大于10(181416)所代表的所有元素之上。我需要的是16,因为它是最远的。

我如何得到它?

3 个答案:

答案 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;
&#13;
&#13;

答案 1 :(得分:1)

要获得满足某些条件的多维数组的最后一个元素,您应该使用某种检查来确保元素是否为数组,以便您知道是否进行递归调用。可以使用Array.isArray查找某些内容是否为数组,或者您可以使用duck-typing并检查length属性。

在数组上向后循环将帮助您更快地找到顶部元素。

&#13;
&#13;
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;
&#13;
&#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