Я пытаюсь реализовать анимацию пузырьковой сортировки на холсте, используя цикл обновления анимации рендеринга.
, так что если ниже указана фактическая не анимированная версия пузырьковой сортировки
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 не поддерживает какую-либо функцию сна, я не могу просто преобразовать приведенный выше код в анимированную версию, показанную ниже
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
}
Частично я могу реализовать это с помощью функции setTimeout.Но я не могу понять, как мы можем полностью изменить рефрактор кода (сравнить и заменить), присутствующий во вложенных циклах, в отдельную функцию (функцию обновления), не теряя состояния индексных переменных.
Поэтому, пожалуйста, позвольтеЯ знаю, есть ли элегантное решение проблемы, следующая моя реализация, развернув циклы в отдельных функциях.Определенно моя реализация не масштабируется, если алгоритм содержит циклы, которые более тесно связаны.
$(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
});