2011-12-23 7 views
0

バブルソートアニメーションをキャンバスに実装しようとしましたが、これは、アップデートレンダーアニメーションループを使用しています。キャンバスを使用したJavascriptのアニメーション

次はバブルの実際の非アニメーションバージョンソート

for(var i = 0 ;i < arr.length - 1; i++) 
    for(var j = 0 ;j < arr.length - 1; j++) 
     if(arr[j] > arr[j+1]) { swap arr[j], arr[j+1]} 

私の要件は今、すべてのスワップに、であるか、比較命令であればそう、すべてのバー(配列要素)が再描画する必要があります。しかし、JavaScriptのdoesnot任意のスリープ機能をサポートするので、私は単に部分的に、私はsetTimeout関数を使用してそれを実装することができる午前

for(var i = 0 ;i < arr.length - 1; i++) 
    for(var j = 0 ;j < arr.length - 1; j++){ 
     if(arr[j] > arr[j+1]) { after swap..... } 
     call to draw method // draw all bars 
     sleep(); // doesnot work in javascript 
    } 

の下に表示アニメーションバージョンに上記のコードを変換することはできません。しかし、私はどのようにしてインデックス変数の状態を失うことなく、ネストされたループの中にあるコードを完全に別の関数(更新関数)に変換する(比較して交換する)ことができないのでしょうか?

問題に洗練された解決方法があるかどうか教えてください 次のコードは私の実装で、ループを別々の関数に展開しています。アルゴリズムがより緊密に配線されたループを含んでいるなら、間違いなく私の実装はスケールされません。

$(function(){ 
    var canvas = $("#mycan"); 
    var ctx = canvas.get(0).getContext("2d"); 
    (function Graph(nBars,ctx){ 
     this.nBars = nBars; 
     this.Bars = []; 
     var MaxBarLen = 250; 
     function Bar(color,height,x,y){ 
      this.color = color; 
      this.height = height; 
      this.width = 10; 
      this.x = x; 
      this.y = y; 

     }; 
     Bar.prototype.toString = function(){ 
      return "height: "+height+" x: "+x+" y: "+y; 
     }; 
     function init(){ 
      //create bars randomly of size 10 - 250 
      for(var i = 0;i < nBars; i++){ 
       Bars.push(new Bar("rgb(0,0,0)", Math.floor(Math.random()*MaxBarLen+10),15*i+1,MaxBarLen)) 
      } 
      algo(); 
      //draw(); 
     }; 
     //method to draw the bars collection to the given context 
     this.draw = function(){ 
      ctx.clearRect(0,0,500,500); 
      for(var i = 0; i < nBars; i++){ 
       if(Bars[i].color == "rgb(0,0,0)") 
        ctx.fillRect(Bars[i].x,Bars[i].y,Bars[i].width,-Bars[i].height); 
       else{ 
        ctx.fillStyle = Bars[i].color; 
        ctx.fillRect(Bars[i].x,Bars[i].y,Bars[i].width,-Bars[i].height); 
        ctx.fillStyle = "rgb(0,0,0)"; 
       } 
      } 
     }; 
     // BUBBLE SORT ALGORITHM 
     var I = -1, J = -1; 
     this.algo = function(){ 
      updateI(); // invocate outer loop 
     }; 
     //outer loop 
     var updateI = function(){ 
      console.log("updateI", I, J); 
      if(I < Bars.length - 1){ 
       J = -1; 
       I++; 
       updateJ(); 

      } 
     }; 
     //inner loop 
     var updateJ = function(){ 
      console.log("updateJ", I, J); 
      if(J < Bars.length - 2){ 
       J++; 
       setTimeout(compare,100); // trigger the compare and swap after very 100 ms 
      }else{ 
       updateI(); 
      } 
     }; 
     //actual compare function 
     var compare = function(){ 
      console.log("compare ", I, J); 
      Bars[J].color = "rgb(0,255,0)"; 
      Bars[J+1].color = "rgb(0,0,255)"; 
      draw(); //draw the frame. 
      if(Bars[J].height > Bars[J+1].height){ 
        //update  
       temp = Bars[J].height; 
       Bars[J].height = Bars[J+1].height; 
       Bars[J+1].height = temp; 
      } 

      Bars[J].color = Bars[J+1].color = "rgb(0,0,0)"; 
      updateJ(); //render next iteration 
     }; 

     //invoke bar creation and bubble sort algorithm 
     init(); 
    })(10,ctx); // 10 bars and context 
}); 

答えて

3

ブラウザに各反復の間に再描画する瞬間を与え、その後、各反復をトリガするためにsetTimeoutを使用してループを書き換えることができます。そのため、おそらく何かのように:

function doIteration(i,j,max,callback) { 
    callback(i,j); 
    if (++j >= max){ 
    j = 0; 
    i++; 
    } 
    if (i < max) 
     setTimeout(function() { doIteration(i,j,max,callback); }, 100); 
} 

var arr = [12, 3, 4, 1, 20, 2, 5, 7, 9, 13, 19, 6, 8, 14, 18, 10, 15, 11, 16, 17]; 

function drawFunction() { 
    document.getElementById("output").innerHTML = arr.join(",") + "<br>"; 
} 

doIteration(0,0,arr.length-1,function(i,j){ 
    var t; 
    if(arr[j] > arr[j+1]) { 
     t = arr[j]; 
     arr[j] = arr[j+1]; 
     arr[j+1] = t; 
    } 
    drawFunction(); 
}); 

iとjと(私は、単一のパラメータとしてそれを残してきたので、それらの両方が同じ最大値を持っていたこの場合)の最大値の開始値とコールdoIteration、および各反復で呼び出され、現在のiとjを渡すコールバック関数。最初にコールバックを呼び出す前に、実際にiとjの値をテストする必要がありますが、読者のための練習として残しておきます。

ここで多くの簡略化の延伸工程でのデモです:私はあなたが一種のすでにこの方向に向かったが、私はあなたの反復はいくつかの機能にまたがった方法が少し混乱したと私がすることが好ましいと思いますhttp://jsfiddle.net/Kpkxw/2/

それを一つの関数に入れてください。

注:あなたが好きそれを行うことができ、これはちょうど私の頭の上から行われる危険な実装の一種であるので、私はスケールするか、それをペイントするためにそれを構築するための時間を持っていなかった...

1

この

var iMax = 10, jMax = 10; 
var i = 0, j=0; 

function firstloop(){ 

    if(i < iMax){ 

    secondloop(); 

    }else{ 

    //final statements 

    } 
} 

function secondloop(){ 

    if(j < jMax){ 

     //statements 

     j++; 
     setTimeout(secondloop, 100)  

    }else{ 

     j = 0;i++; 
     firstloop(); // You can add a time out here if needed 
    } 

} 

firstloop(); 
関連する問題