オブジェクト指向っぽくオセロを作る4
- オブジェクト指向っぽくオセロを作る
- オブジェクト指向っぽくオセロを作る2
- オブジェクト指向っぽくオセロを作る3
- オブジェクト指向っぽくオセロを作る5
- オブジェクト指向っぽくオセロを作る6
- オブジェクト指向っぽくオセロを作る7
- オブジェクト指向っぽくオセロを作る8
- オブジェクト指向っぽくオセロを作る9
- オブジェクト指向っぽくオセロを作る10
- オブジェクト指向っぽくオセロを作る(まとめ)
Viewオブジェクトの続きです。
少し発展
前回Viewオブジェクトのpaintメソッドが呼ばれるたびに、毎回全てのセルが削除されるという話をしました。しかし、全てのセルを描写しなおすのではなく、変更された箇所のみ描写しなおすほうが効率が良いでしょう。ここでは変更のあった箇所のみ描写しなおす処理を記述します。ちなみに以前の処理は効率が悪いだけであって、ゲームを進行する上では問題ありません。
var View = { /** * Boardクラスから生成したboardオブジェクトをセットする */ setBoard : function(board){ this._board = board; }, /** * boardの情報を実際に盤として描写するための処理 * 変更された箇所のみを再度描写しなおす */ paint : function() { /** * 指定された種類のセルのDOM要素を作成する * typeはblack, white, emptyのいずれか * なお、この関数はpaintメソッド内でのみ有効 */ var makeElement = function(type,id,x,y){ var element; if(type != "black" && type != "white" && type != "empty"){ throw new Error("illegal argument 'type': "+type); }else{ element = document.getElementById(type).cloneNode(true); if(!element) throw new Error("idが"+type+"のDOM要素をクローンできませんでした。"); } element.style.left = 32 * x + "px"; element.style.top = 32 * y + "px"; element.id = id; return element; }; if(!this._board) throw new Error("board is null/undefined. please call setBoard method before paint."); var board_element = document.getElementById("board"); for ( var y = 0; y < 8; y++) { for ( var x = 0; x < 8; x++) { /* * boardオブジェクトが示す駒と * DOM要素が示す盤の駒を比較 * 差異がある場合だけ描写を行う */ var nType; //boardオブジェクトの示す駒の種類 switch ( this._board.getPiece(x, y) ) { case Piece.BLACK: nType="black"; break; case Piece.WHITE: nType="white"; break; case Piece.EMPTY: nType="empty"; break; } //DOM要素の示す駒を取ってくる var id = "cell" + (x + 1 + y * 8); //idはcell1からcell64まで var bElement = document.getElementById(id); if(bElement){ //一番最初はDOM要素がないのでエラーではない var bType = bElement.className; //classは駒の種類に対応している } //同じなら描写しなおす必要がないので次の周に if(nType && bType == nType) continue; else{ //違うなら if(bElement) //なおかつ現在DOM要素があるなら board_element.removeChild(bElement); //DOM要素を取り除く } //新たに追加するDOM要素を作る var nElement = makeElement(nType, id, x, y); if(nElement){ board_element.appendChild(nElement); } } } } };
paintメソッドをご覧ください。ここでは最初にmakeElementという関数を設けました。これは指定されたDOM要素を作成するための関数です。なお、この関数はpaintメソッドの内部でのみ有効となります。次に二重になっているfor文の内側をご覧ください。ここではまず、boardオブジェクトの示す駒の情報を取得しています。次にDOM要素が表す駒の情報を取得しています。前に各セルのidはcell1からcell64までのいずれかになるという話をしました。このidを元にして、セルのDOM要素を取得しています。そして次にセルのDOM要素がきちんと取得できたのか調べます。ただし一番最初、つまり何も描写されていない状態ではDOM要素は取得できません。そのため、DOM要素が取得できなくてもエラーではありません。次にDOM要素からclassを取得しています。classの値は駒の種類、つまりblack、white、emptyのいずれかに対応しています。
boardの示す駒の種類と、DOM要素の示す駒の種類が分かりました。ここでこの二つを比較します。そして差異がある場合だけ、古いDOM要素を削除した後、新しいDOM要素を作成して追加しています。
ここまでのまとめ
ここまでのソースコード一式を載せておきます。バグがあれば、報告していただけると嬉しいです。
oop-othello.zip
次回はいよいよゲームの流れを管理する「オセロのルール」に対応するOthelloオブジェクトを作っていきます。
Othelloオブジェクトを作ろうかと考えていたのですが、Viewオブジェクトに少し手を加えることにしました。