7日目:jQueryライブラリを使ってみる

7日目です。少しプログラムが長くなって複雑(じゃないけど)になってきたっぽいので、ここは1つ有名なjQueryライブラリを使ってコンパクトにしてみたいと思います。jQueryライブラリは検索すると大量に出てきますが、ブラウザ間の差違を吸収してくれたりDOM要素の指定を短く記述することができたりする便利なライブラリです。機能の割にファイルサイズは小さめです。
jQueryライブラリのサイトは以下のURLにあります。

http://jquery.com/

jQueryライブラリのダウンロードは以下のページから行えます。

http://jquery.com/download/

2014年12月29日時点では最新バージョンは2.1.3なので、これをダウンロードして使います。直接CDNで指定してもいいのですけど、電波の来ない山間地ではCDNは辛いのでダウンロードしておくのが無難どころ。
jQueryライブラリを使う場合はHTMLで以下のようにして読み込ませます。

<script src="jquery-2.1.3.min.js"></script>

あとはDOM要素の指定を$()に置き換えるくらい。で、実際に置き換えた部分は以下のソースコードのコメントの●印をつけてある行になります。それで、ぱっと見だとjQueryの恩恵がほとんどないという事に気づいてしまいます・・・。jQueryのメリットの1つとして複数のDOM要素に対して一括して処理(イベントとか)できるというのがあります。が、今回のゲームでは初期化時やゲームクリア後のvar ele = $("input").click(addNumber);のイベント割り当てしかメリットがなかったりします。まとめて指定して、どうにかするという処理がない場合jQueryは効果がない感じです。
そして、もう1つ。jQueryライブラリが誕生してから、もう10年近くになります。その間にブラウザが大幅に進化し標準化が進み機能も豊富になりました。なので、jQueryのメリットが見えにくくなっているというのもあります。昔は$()によるセレクタは便利でしたが、今はブラウザネイティブでvar ele = document.querySelectorAll("input");で済んでしまいます。
こうなると、このゲームにjQueryライブラリを使うメリットが、あまりなさそうです。そして、さらにゲームを改良したりしていくとなると新たな問題がでてきそうです。それはjQueryを使うことのデメリットです。まず、思い浮かぶのがjQueryのバグ。これが発生したら修正されるまで待たないといけません。また、仕様変更されたらプログラムの修正が必要になります。そして、いつまでjQueryが存在するかという問題です。ライブラリは大量に出て大量に死滅する運命なので、jQueryもその可能性はあります。結論から言えばjQueryに振り回されたくない、ということです。
ということで、しばらくはjQueryライブラリは使わないことにします。というか、使う機会があるかどうか謎です。ブラウザネイティブのJavaScriptの方が高速ですし、バグがあってもブラウザレベルでの対処で済みます。

ということで、次回は1つ前のプログラムに戻って、そこから再度移植&改良を始めることにします。まあ、やってみて失敗することもあります。やってみないと分からない事はありますが、いろいろ作っていくと最初から不具合が発生しないようにできるノウハウもたまります。ひどいこと言えばプログラムはバグを出さなければ早く作成することができるわけなので。

[サンプルを実行する]

[サンプルをダウンロード]

HTMLファイルの内容

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>TEN</title>
<style>
input { width:48px; height: 48px; background-color: white; font-size: 24pt; }
#clearMsg { position : absolute; left: 10px; top: 200px; font-size: 18pt; color: red; visibility: hidden; }
</style>
</head>
<body>
<h1>TEN</h1>
<div>SCORE : <span id="score">0</span></div>
<form>
<!-- 1段目 -->
<input type="button"><input type="button"><input type="button"><input type="button"><br>
<!-- 2段目 -->
<input type="button"><input type="button"><input type="button"><input type="button"><br>
<!-- 3段目 -->
<input type="button"><input type="button"><input type="button"><input type="button"><br>
<!-- 4段目 -->
<input type="button"><input type="button"><input type="button"><input type="button"><br>
<!-- 5段目 -->
<input type="button"><input type="button"><input type="button"><input type="button"><br>
<!-- 6段目 -->
<input type="button"><input type="button"><input type="button"><input type="button"><br>
</form>
<div id="msg"></div>
<div id="clearMsg">ステージクリア!</div>
<script src="jquery-2.1.3.min.js"></script>
<script src="main.js"></script>
</body>
</html>

JavaScriptファイル (main.js) の内容

// TEN HTML5 version
// (c) 2014 Cybermuse
// Arranger 古籏一浩
var score = 0;			// スコア(得点)を入れる変数
var count = 0;		// ボタンの合計を入れる変数
var prevNumber = 0;	// 直前にクリックした数字を入れる変数
var prevEle = null;		// 直前にクリックした要素を入れる変数
// 初期化処理
function init(){
	var ele = $("input").click(addNumber);	// ●クリックしたら処理するようにイベントを設定
	count = ele.length;	// input要素の総数を入れる
	setRandomValue(ele);	// input要素の数を渡す
}
// ランダムに値を設定する関数
function setRandomValue(ele){
	var len = ele.length;	// input要素の総数
	// input要素にランダムな値を設定する
	var num = [ ];
	for(var i=0; i<len; i+=2){	// 要素の数だけ繰り返す
		var n = Math.floor(Math.random() * 9) + 1;	// 1〜9までの数値をランダムに生成する
		num.push(n);
		num.push(10 - n);
	}
	// 配列要素をele.length回シャッフルする
	for(var i=0; i<len; i++){
		var p1 = Math.floor(Math.random() * len);	// input要素の数の範囲で乱数を発生させる
		var p2 = Math.floor(Math.random() * len);	// input要素の数の範囲で乱数を発生させる
		var n = num[p1];	// 2つの要素の内容を入れ替える
		num[p1] = num[p2];
		num[p2] = n;
	}
	// input要素に値を設定する
	ele.each(function(i){	// ●イテレーターで処理
		ele[i].value = num[i];	// 値を設定する
	});
}
// 2つの数字の合計が10かどうか調べる
function addNumber(){
	// 1個目のクリックの場合
	if (prevNumber === 0){
		prevEle = this;	// 要素の情報を変数に入れる
		$(prevEle).css("backgroundColor", "red");	// ●背景を赤色にする
		prevNumber = parseInt(this.value);	// クリックされた要素の番号を変数に入れる
		return;	// 関数から抜ける
	}
	// 2個目のクリックの場合
	var total = prevNumber + parseInt(this.value);	// 直前の数値とクリックされた要素の数値を加算する
	if (total === 10){	// 合計が10の場合の処理
		$(this).css("visibility", "hidden");	// ●現在の要素を非表示にする
		$(prevEle).css("visibility", "hidden");	// ●前の要素を非表示にする
		prevNumber = 0;	// 数値を0にする
		$("#msg").html("OK!");	// ●メッセージを表示する
		score = score + 1;	// スコア(得点)を追加する
		$("#score").html(score);	// ●スコア(得点)を表示する
		count = count - 2;	// 合計から2を引く
		if (count === 0){	// 全部消したかどうか調べる
			$("#clearMsg").css("visibility", "visible");	// ●ステージクリアメッセージを表示する
			setTimeout(function(){	// 2秒後に表示されているメッセージを消すためのタイマー
				$("#clearMsg").css("visibility", "hidden");	// ●ステージクリアメッセージを消す
				var ele = $("input");	// input要素を取得する
				setRandomValue(ele);	// 乱数値を設定する
				ele.each(function(i){	// ●イテレーターで処理
					$(ele[i]).css("visibility", "visible");	// ●表示する
					$(ele[i]).css("backgroundColor", "");	// ●透明にする
				});
				count = ele.length;	// input要素の総数を入れる
				$("#msg").html("");	// ●メッセージをクリア
			}, 2000);
		}
		return;	// 関数から抜ける
	}
	// 合計が10でなかった場合
	prevNumber = 0;	// 数値を0にする
	$(prevEle).css("backgroundColor", "");	// ●透明にする
	$("#msg").html("合計が10じゃないよ!");	// ●メッセージを表示する
}
init();	// 初期化処理を呼び出す