I am trying to implement bubble sort animation on canvas using the update render animation loop.
so if following is the actual non animated version of bubble sort
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]}
my requirement now is, on every swap or compare instruction, all the bars(array elements) should be re-drawn. But since javascript doesnot support any sleep function i cannot simply convert the above code to animated version shown below
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
}
Partly I am able to implement it using setTimeout function. But I am unable figure out, how can we refractor the code(compare and swapping) present inside the nested loops completely into a separate function(update function) with out loosing the state of index variables.
So please let me know if there is any elegant solution to the problem following is my implementation by unrolling the loops in to separate functions. Definitely my implementation doesnot scale if the algorithm contains loops that are more tightly wired up.
$(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
});