我需要一个递归函数来解决这个问题吗?

JavaScript: Do I need a recursive function to solve this problem?

本文关键字:解决 问题 递归函数 一个      更新时间:2023-09-26

在此小提琴http://jsfiddle.net/5L8Q8/28/中,如果单击黑色按钮,它会从数组中随机选择两个值(红色或蓝色)中的一个。将随机选择的值赋给ran。在我的实际应用程序中,该数组中将有16个元素。

如果你选择粉红色的"playagain"按钮,它会从相同的数组中选择一个随机元素,但我想确保它不是上次选择的那个。

因此,当我点击playagain时,我将ran分配给lastran,并将其与从数组中随机选择的下一个值进行比较,如果它们相同,则再次随机选择。然而,我拥有它的方式并不能保证(在playagain完成后)ran是不同的。

我认为我需要一个递归函数,其中注释2在下面的代码中,但是当我试图创建它时,我不断破坏我的代码。

你能对下面代码中的3个注释进行注释吗?

注意,我是一个新手,所以这段代码可能很糟糕…

$("#playagain").click(function(){
    lastran = ran; 

    ran = getRandom(myArray, true);
    if (ran === lastran) { 
        ran = getRandom(myArray, true); //1. do I need to return this?
           //2. want to test ran === lastran again.. How to set up recursive function?
    } else {
       return; //3.is this the right thing to do here?
    }  
});
while( (ran = getRandom(myArray, true)) === lastran)
    ;

就是你想要的。该声明

ran = getRandom(myArray, true)

不仅将ran设置为getRandom(),而且返回ran的值。(这是JavaScript中相当常见的习惯用法,从c继承而来)

所以你的完整代码可以是:
$("#playagain").click(function(){
    /*var */lastran = ran; 
    while( (ran = getRandom(myArray, true)) === lastran)
        ;
    // update UI here
});

可以使用while循环来代替if。

while(ran == lastran)
{
  ran = getRandom(myArray, true);
}

它会一直尝试直到得到不同的值

每次运行后,只需从数组中删除该"key"并将lastan推到数组的末尾。然后更新getRandom函数,如下所示,可以同时用于#button和#playagain。http://jsfiddle.net/ghostoy/5L8Q8/32/

function getRandom(array, getVal) {
    var key = Math.floor(Math.random() * array.length),
        value = array[key];
    if (lastran) {
        array.push(lastran);
    }
    array.splice(key, 1);
    lastran = value;
    if (getVal) {
        return value; 
    }
    return key; 
}

我认为你的方法不是处理这件事的最好方法。从理论上讲,你可以连续多次得到相同的数字,这是一个"缓慢"的算法,而且你正在使它变得比需要的更复杂。

文本中的替代方法:

- if no previous element has been picked pick a number between 0 and the number of elements in your array (16) otherwise pick a number between 0 and #elements-1 (15)
- if the chosen element is greater or equal to the last element picked add 1 to it 
- store this index number as the last picked element
- return the array[picked-element]'s value

你可以让getRandom本身递归:

function getRandom(array, getVal, lastRan) { 
    var key = Math.floor(Math.random() * array.length);
    if ((!getVal && key == lastRan) || (getVal && array[key] == lastRan))
        return getRandom(array, getVal, lastRan);
    return getVal ? array[key] : key;
}

调用它传递最后一个随机值:

getRandom(myArray, true, lastran)

它是这样工作的。您总是将最后一个检索到的随机值传递给getRandom。在第一个条件中,我们检查是否刚刚生成了该值的副本(使用键本身或其在数组中的对应值,取决于getVal是否为true)。如果是,则返回再次调用getRandom的结果,并再次传递使用的最后一个随机数。如果有必要,这种情况可以发生很多次。

当其中一个对getRandom的调用产生一个新数字时,第一个条件中的表达式将为false。在这种情况下,我们返回所需的值(通过第二个return语句),并且对getRandom的所有递归调用都被"展开"。(请记住,我们在每一步都将每次调用的值返回给getRandom。)