2013-05-24 3 views
2

Рассмотрим следующий блок кода, выполнить несколько раз (jsFiddle):Bizarre do..while поведение: не могли бы вы объяснить?

var length = 50, 
    xOffset = 0, 
    yOffset = 0; 
for (var a = 0; a < 100; ++a) { // just so we can see it "break" 
    for (var l = 1; l <= length; l++) { 
    var percentComplete = l/length, 
     scaledPercent = (.5 - Math.abs(percentComplete - .5)) * 2, 
     shake = 0, 
     shakeTries = 0, 
     deviationCeil = Math.ceil(10 * scaledPercent); 
    if (Math.random() < .1 || Math.abs(xOffset) > deviationCeil) 
     do { 
     shake = Math.floor(Math.random() * 3) - 1; 
     if (++shakeTries > 100) throw "X shake exceeded" 
    } 
    while (Math.abs(xOffset + shake) > deviationCeil); 
    xOffset += shake; 
    shakeTries = 0; // if we set shake = 0 here, everything works! 
    if (Math.random() < .1 || Math.abs(yOffset) > deviationCeil) 
     do { 
     shake = Math.floor(Math.random() * 3) - 1; 
     if (++shakeTries > 100) throw "Y shake exceeded" 
    } 
    while (Math.abs(yOffset + shake) > deviationCeil); 
    yOffset += shake; 
    } 
} 

При запуске повторно, «трясти Y превышена» исключение выбрасывается (далее «трясти X превышена» никогда не выброшены).

Решение состоит в том, чтобы установить shake в 0 непосредственно перед блоком Y: .

Я не понимаю, почему это должно быть так. В обоих блоках мы начинаем с назначения на тряску, поэтому на самом деле не важно, какой ад был shake, до перехода в блок do. Мое понимание do...while (и причина, по которой я его использую) заключается в том, что он сначала выполняет свой блок перед тестированием условия.

Так почему же это происходит неудачно (не каждый раз), когда я не сбрасываю shake перед do блоком?

+0

не могли бы вы правильно отступить от кода – aaronman

ответ

3

Это странное поведение становится более заметным, если мы добавим некоторые дополнительные { и }. Давайте сначала рассмотрим только раздел X. В начале, как трясти и shakeOffset равна 0.

if (Math.random() < .1 || Math.abs(xOffset) > deviationCeil) { 
    do { 
    shake = Math.floor(Math.random() * 3) - 1; 
    if (++shakeTries > 100) throw "X shake exceeded" 
    } while (Math.abs(xOffset + shake) > deviationCeil); 
} 
xOffset += shake; 

На данный момент, дрожание имеет любое значение, в последний раз использовали в предыдущем кадре (-1, 0 или 1). Затем мы перейдем к разделу Y:

shakeTries = 0; // if we set shake = 0 here, everything works! 
if (Math.random() < .1 || Math.abs(yOffset) > deviationCeil) { 
    do { 
    shake = Math.floor(Math.random() * 3) - 1; 
    if (++shakeTries > 100) throw "Y shake exceeded" 
    } while (Math.abs(yOffset + shake) > deviationCeil); 
} 
yOffset += shake; 

Если мы не отвечаем условия (Math.random() < .1 || Math.abs(yOffset) > deviationCeil), то мы пропускаем do...while целиком и добавить значение сотрясения из раздела X в YOffset.

+0

Я хочу сказать, что это правильно, но я переключил места двух разделов, а затем он не выбрасывает – aaronman

+0

nvm your correct – aaronman

+0

Oh man. Я знал, что это что-то в моей логике - и когда вы указываете это, это становится таким __обвиняем! Спасибо, что нашли время. Все сводится к тому, что Math.random() <.1 часть, которая была поздним дополнением. Еще раз спасибо! Отличное объяснение. –

Смежные вопросы