Применение кнопки для каждого шага или задержка рекурсии JavaScript - PullRequest
0 голосов
/ 27 ноября 2018

Я создал небольшую программу с использованием JavaScript для решения проблемы Ханойской башни.Я использовал 3 башни DIVs и дал первую башню черного цвета, а для остальных я дал белый.Когда я хочу, чтобы программа поменяла 2 элемента, она в основном меняет свойства соответствующих DIV.Код работает отлично, но я хочу, чтобы каждый шаг был видимым, и в текущем состоянии это всего лишь вспышка от начала до конца.Я пытался использовать кнопку для каждого шага, и это не сработало, и поэтому setTimeout ().(Извините за мою плохую Англию: c)

var from = 1;
var to = 2;
var help = 3;

function swap(from, to){
    while (...){
        if (...){
            while(...){
                if (...){
                    //swaps the properties of the divs
                }
            }
        }
    }
}


function hanoi(n, from, to, help){
    if (n == 1){
        swap(from, to);
    }
    else{
        hanoi(n-1, from, help, to);
        swap(from, to);
        hanoi(n-1, help, to, from);
    }
}

Я пробовал это, но это только задержало вспышку на 2 секунды:

function hanoi(n, from, to, help){
    if (n == 1){
        setTimeout(function(){swap(from, to);}, 2000);
    }
    else{
        hanoi(n-1, from, help, to);
        setTimeout(function(){swap(from, to);}, 2000);
        hanoi(n-1, help, to, from);
    }
}

Ответы [ 2 ]

0 голосов
/ 27 ноября 2018

Я настоятельно рекомендую проверить, как setTimeout работает со стеком событий JavaScript. Вот потрясающее видео .

Вот ваш процесс.

  1. Вы вызываете hanoi, который, если он проходит проверку if, автоматически вызывает себя снова.
  2. Поскольку setTimeout отправляет выполнение этого кода в веб-интерфейс для выполненияпозже он автоматически запускает второй hanoi в этом блоке.
  3. Это продолжит запускать hanoi с и создавать больше setTimeouts, которые отправляют выполнение swap в webapis.
  4. Поскольку все ваши setTimeouts запускаются одновременно", они решают свои 2 секунды ожидания одновременно.

Ответ Джонаса Уилмса объясняет, как решить эту проблему.

0 голосов
/ 27 ноября 2018

В вашем последнем блоке кода рекурсивная функция выполняется рекурсивно, создает все тайм-ауты, и через 2 секунды все тайм-ауты перезваниваются вскоре после другого, поэтому она мигает ( в подробном объяснении ).Вместо этого вы также хотите отложить рекурсивный вызов:

 function hanoi(n, from, to, help){
   if (n == 1){
    setTimeout(function(){swap(from, to);}, 2000);
   } else{
    setTimeout(function() {
       hanoi(n-1, from, help, to);
       swap(from, to);
       hanoi(n-1, help, to, from);
    }, 2000);
  }
}

Однако, хотя это работает, этот код не очень красив.На самом деле, Ханойский метод не визуализирует и не задерживает цикл.Вместо этого я написал бы логику Ханоя в методе, который может быть прерван, а затем он может быть вызван функцией-обработчиком, которая выполняет рендеринг и задержку.Это идеальный вариант использования для генераторов:

 function* hanoi(n, from, to, help){
    if (n == 1){
     swap(from, to);
    } else{
       yield* hanoi(n-1, from, help, to);
       swap(from, to);
       yield* hanoi(n-1, help, to, from);
   }
   yield; // Pass execution back to the "runStepByStep" loop, rerendering & delaying happens here
}

И обработчик:

 const timer = ms => new Promise(resolve => setTimeout(resolve, ms));

 async function runStepByStep(iterator) {
   let done = false;
  do {
    ({ done } = iterator.next());
    rerender(); // TODO: Implement this
    await timer(2000);
  } while(!done);
}

 runStepByStep( hanoi(10, 0, 2, 1) );
...