2

次のコード ブロックを考えて、繰り返し実行します ( jsFiddle )。

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解決策は、Y ブロックの直前に 0を設定することですshake = shakeTries = 0

なぜこれが必要なのかわかりません。両方のブロックで、シェイクに割り当てることから始めます。そのため、ブロックshakeに入る前に、一体何があったかは問題ではありません。do私の理解do...while(および私がそれを使用している理由)は、条件をテストする前に最初にブロックを実行することです。

では、ブロックshakeの前にリセットしないと (毎回ではなく) 失敗するのはなぜですか?do

4

1 に答える 1

3

{と を追加すると、この奇妙な動作がより顕著になり}ます。最初に X セクションだけを見てみましょう。最初は、shake と 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 にシェイクの値を追加します。

于 2013-05-24T02:19:53.130 に答える