Webブラウザ上でバブルソートの可視化

少々冗長なコードになってしまったがバブルソートを可視化できたのでメモ

グラフ（html）を何度も再描画しているのでシンプルに処理が遅い(笑)
Ajaxを使ったら早くなる・・・のだろうか？
Ajaxは今後触れる予定
setIntervalを使わないと関数を実行してから終了形まで一気にグラフが描画されてしまうのでグラフが並び変わっていく様を楽しめなかった。
これは一つの関数が実行し終えるまでhtmlは再描画できないという仕様なのだそう。（当然のことではあるが・・・）
よってsetIntervalで一回一回並び替えをするごとに関数を終了させ、それを短いスパンで繰り返している。
音源は適当な機械音を鳴らしている。

バブルソート↓clickすると動画が再生されます
[![バブルソート](https://qiita-image-store.s3.amazonaws.com/0/203798/3b7f9212-e598-a69f-4be5-e971294787c0.png)
](https://www.youtube.com/embed/YDbFYH81LO0)
**html**
genGraph()関数でdiv要素内ににグラフを生成する
dummyクラスは値をheightとwidthに保持するダミー要素

```html:index.html
<!DOCTYPE htlm>
<head>
	<meta charset="utf-8">
	<title>sort</title>
	<link rel="stylesheet" type="text/css" href="css/style.css">
	<link rel="stylesheet" type="text/css" href="css/bootstrap-4.0.0-beta.2-dist/css/bootstrap.min.css">
	<audio src="sound.mp3" loop autoplay="auto"></audio>
</head>
<body>
	<div id="wrap" onClick="genGraph()"></div>
	<div onClick="funcStart()">change</div>
	<div class="dummy"></div>
	<div class="iValue">i = 0</div>
	<div class="jValue">j = 0</div>
	<script type="text/javascript" src="js/jquery-3.2.1.min.js"></script>
	<script type="text/javascript" src="js/javascript.js"></script>
</body>
</html>
```

**jQuery**
numはグラフの数を表し、自由に設定可能、以下関数説明

genGraph()・・・グラフをnumの数だけ生成し、それぞれのグラフに異なるidを付与
generate_randomx(count)・・・重複しない乱数をnumの数だけ生成し、グラフのheightに割り当て
changeGraph(x, y)・・・idがxとyの要素の高さを入れ替える
getArray()・・・実行時のグラフの各々のheightを配列に格納しその配列を返す
bbsor(arr, i, j)・・・バブルソートのアルゴリズムを実行し、その結果をdummyクラスのheightとwidthに格納
prepare()・・・アルゴリズム実行の前準備
funcStart()・・・setIntervalを用いてhtmlを再描画している
timerOff()・・・setIntervalをストップしdummyクラスを初期化
prepare2(flag)・・・処理が完了し、グラフを緑に塗り替えるための前準備
changeColor(i)・・・グラフの背景色を左から右へgreenに変える

```js:javascript.js
var num = 100;

function genGraph() {
	var str = "<div class='graph' id=no" + 0 +"></div>";
	for (var i = 1; i < num; i++) {
		str += "<div class='graph' id=no" + i +"></div>";	
	}

	$("#wrap").html(str);
	var arr = new Array();
	arr = generate_randomx(num);

	for (var i = 0; i < num; i++) {
		rand = arr[i];
		rand = rand * 4 + 'px';
		var no = "#no" + i;
		$(no).css('height', rand);
	}
}
function generate_randomx(count) {
  //生成した乱数を格納する配列を初期化
  var generated = new Array();
  //生成した乱数を格納している配列の長さ（生成した乱数の数）
  var generatedCount = generated.length;
  //パラメータ count の数だけ Math.random()で乱数を発生
  for(var i = 0 ; i < count; i++){
    var candidate = Math.floor(Math.random() * count);
    //今まで生成された乱数と同じ場合は再度乱数を発生
    for(var j = 0; j < generatedCount; j++) {
      if(candidate == generated[j]){
        candidate = Math.floor(Math.random() * count);
        j= -1;
      }
    }
    generated[i] = candidate;  
    generatedCount++;
  }
  return generated;  
}

function changeGraph(x, y) {
	var xHeight = $(x).outerHeight();
	var yHeight = $(y).outerHeight();
	var temp = xHeight;
	xHeight = yHeight;
	yHeight = temp;
	$(x).css('height', xHeight + 'px');
	$(y).css('height', yHeight + 'px');
	for (var i = 0; i < num; i++) {
		$('#no' + i).css('background-color', '#fff');
	}
	$(x).css('background-color', 'red');

}

function getArray() {
	var arr = new Array(0);
	for (var i = 0; i < num; i++) {
		var noHeight = $("#no" + i).outerHeight();
		arr.push(noHeight);
	}
	return arr;
}

function bbsor(arr, i, j) {
	console.log("i:" + i);
	console.log("j:" + j);

	j -= 1;
	if (j == i) {
		i +=1
		j = num - 1;
	}

	if (arr[j] < arr[j - 1]) {
		temp = arr[j];
		arr[j] = arr[j - 1];
		arr[j - 1] = temp;
		var x = '#no' + j;
		var dummy = j - 1;
		var y = '#no' + dummy;
		changeGraph(x, y);
	}
	if (i == 0 && j == 0) {
		i += 1;
	}
	$(".dummy").html(arr);
	$(".dummy").css('height', i + 'px');
	$(".dummy").css('width', j + 'px');

	console.log(arr);
}

function prepare() {
	arr = getArray();
	var i = $('.dummy').outerHeight();
	var j = $('.dummy').outerWidth();
	if (i == 0 && j == 0) {
		var j = num;
	} else {
		var j = $('.dummy').outerWidth();
	}
	if (i == num - 1 && j == 0) {
		timerOff();	
	}
	bbsor(arr, i , j);
	$(".iValue").html('i = ' + i);
	$(".jValue").html('j = ' + j);
}

function funcStart() {
	timer = setInterval('prepare()', 1);
}

function timerOff() {
	clearInterval(timer);
	$('.dummy').css('height', '0px');
	timer2 = setInterval('prepare2()', 10);	
}

function prepare2(flag) {
	a = $('.dummy').outerHeight();
	console.log(a);
	if (flag == 0) {
		i = 0;
	} else {
		var i = $('.dummy').innerHeight();
	}
	changeColor(i);
}

function changeColor(i) {
	k = i - num + 1;
	$('#no' + k).css('background-color', 'green');
	i += 1;
	$('.dummy').css('height', i + 'px');
	if (k == num - 1) {
		clearInterval(timer2);	
	}
}
```

```css:style.css
#wrap {
	width: 100%;
	height: 500px;
	background-color: #191919;
	display: flex;
	align-items: flex-end;
}

.graph {
	/*border: 1px solid #ccc;*/
	height: 5px;
	width: 10px;
	background-color: #fff;
}

.dummy {
	display: none;
	height: 0;
	width: 0;
}

.iValue {
	position: absolute;
	top: 20px;
	left: 20px;
	color: #fff;
}

.jValue {
	position: absolute;
	top: 40px;
	left: 20px;
	color: #fff;
}
```

クイックソートも作りたい。

ちなみにyoutubeでsortって調べるともっとすごい人がつくってるやつでてくるのでオススメ(今回はそれを参考に作った)