前回の記事はこちら
自力でリバーシ(オセロ)を作っていく#00
次回の記事はこちら
自力でリバーシ(オセロ)を作っていく#02
#これからの記事の書き方
これからの記事のフォーマットを決めておこうと思います。
自分が描きやすく、また見返しやすくするためです。
- 導入(これはないかも
- 進捗
- 作った処理の流れ説明
- 詰まった部分
- できれば改善したい部分
- 学んだこと(今後の予想なども)
こんな感じでやってみます
#今回の進捗
実装完了した処理は
- 8*8のマス描画
- クリックで石置ける
- ヨコではさまれたら色変更
この3つだけです笑
前回の、必要な処理列挙と3つの実装だけで5時間くらいかかっちゃいました。
#作った処理の流れ説明
- 8*8のマス描画
- クリックで石置ける
- ヨコではさまれたら色変更
この3つについて、順に書いていきます
##88のマス描画
今回はまず88マスの描画をするところから取り掛かったのですが、いきなりかなり悩みましたね〜
後から操作しやすいHTMLにしたかったので、何がいいのか結構考えました。
- テーブルで作るか
- ひとマスをcanvasで作り 、繰り返すか
- シンプルにdivだけでいくか
僕が思いついたのはこの3つでしたね。
テーブルでの作成は、タテヨコが制御しやすいかな?とか思って選択肢に出したのですが、よく考えると全然そんなことなさそうなので不採用にしました。
canvasで全体のマス描画という案も一瞬浮かんだのですが、クリックイベントが使いにくくないそうなので即却下しました。
ひとマスをcanvasで作ってそれをループさせる案をとりあえず採用したのですが、僕の力不足でうまくいかず断念しました(canvas使いたかったぁ…
こんな感じで最終的にdivで作成していくことに決定しました(消極的選択!
divでの作成に決めるとマス描画は一瞬でした笑
早くjavascriptでの処理に取り掛かりたい気持ちでいっぱいでしたね。
<div class=”row”>
<div class=”rectangle”></div> *8
・
・
・
</div>
これを8個作って、テキトーにborderとサイズを決めて終わりです。
ついでに、黒石と白石をそれぞれ、black-stone/white-stoneというクラスの擬似要素で作成ました。
クリックや色変更の時に、このクラスの有無で制御する予定です。
##クリックしたら石置ける
ここからは、「クリックで石が置ける」、「ヨコではさまれた時に色が変わる」処理について考え始めました。
まず、
- 石を置いた場所
- 左右斜めにある石
を簡単に取得できるようにしたかったので、ここをどう処理するか考えました。
全てのマスにidをふる案が最初に思いついたのですが、これではあまりにもやっつけすぎるというか、アホっぽい気がしたのでやめました。
結局左下から順に
(x1,y1)/(x1,y2)
というようなクラスをふることになりました。
(x1,y7) | (x2,y7) | (x3,y7) |
---|---|---|
(x1,y6) | (x2,y6) | (x3,y6) |
(x1,y5) | (x2,y5) | (x3,y5) |
(x1,y4) | (x2,y4) | (x3,y4) |
(x1,y3) | (x2,y3) | (x3,y3) |
(x1,y2) | (x2,y2) | (x3,y2) |
(x1,y1) | (x2,y1) | (x3,y1) |
ここからがやっとJSでの処理ですね。
とりあえず簡単に考えるために黒石のみの操作で進めていきます。
まず
className('rectangle')でマスを全部取得して、クリックされたマスを取得するために次のようにしました。
for (let i = 0; i < rectangleObject.length; i++) {
rectangleObject[i].addEventListener('click', () => {
//石置いて、はさめたら白色をひっくり返す処理
putBlackStone(rectangleObject[i]);
}, false);
}
putBlackStone(obj)を考えていきます。
まずクリックされたマスにclass="black-stone"を追加したいのですが、その前に
すでにそのマスに石が置いてないかどうか
を確認してから、なければ石を置くような処理にします。
なので、ここではclassList.containsを使用して次のようにしました。
function putBlackStone(obj) {
if (obj.classList.contains('white-stone') == true) {
alert('そこにはすでに白石があります');
}else if (obj.classList.contains('black-stone') == true) {
alert('そこにすでに黒石があります');
}else {
obj.classList.add('black-stone');
//はさんだ石の色を変更する処理
reverseStone(obj);
}
}
これでひとまず、クリックされたマスに黒石を置く処理は完了です。
次にはさんだ色を変更する**reverseStone(obj);**の中身を考えていきます。
ヨコではさまれたら色変更
この部分でだいぶ苦戦しました。
ていうか、正直まだ未完成です笑
処理の流れとしては
- クリックされたマスの座標取得
- 同じy座標(水平方向)で黒石があるか確認
- 黒石があれば間に白石があるか確認
- 黒石間が白石で隙間なく埋まっているか確認
- 埋まっていれば白石を黒石に変更
この処理の流れを考えるのが今回の挑戦の目的なので、苦戦しましたがかなり楽しかったですね。
#詰まった部分
今回の作業で詰まった箇所は次の点です。
- Canvasの繰り返し描画
- クリックされた隣のマスの取得
##Canvasの繰り返し描画
Canvasでひとマス描画して、それをjavascriptのループを使用して8*8のマスを作成ようと考えていました。
Canvasの初使用でウキウキのまま、まず
<canvas class="rectangle"></>
を出力するためにdocument.writeの使用を検討しました。
調べているとdocument.writeはHTML5では非推奨ということなので使用をやめ、innerHTMLを使ってみることにしました。
ですが、<div></div>
のなかに入れ子で出力がうまくできず断念しました…
ここはまたリベンジしたいですね。
クリックされた隣のマスの取得
ここは当然用意していた座標の出番だ、とニッコリしていたのですが、実際隣を取得するには
クリックしたマスのx座標に±1したx座標を作らないといけないというところで詰まりました。
結局以下の感じの処理でいきました。若干ゴリ押しなのかな?
- クリックしたマスのx座標クラスを取得
- 文字列のx座標の数字部分をperseIntで数値として取得
- 演算ができるのであとは自由に
//例)element = ["rectangle","x5","y5"]
//例)numの中身はx5
var num = element.match(/[0-9]+/);
//例)xnumの中身は数値型の5
var xnum = parseInt(num, 10);
#できれば改善したい部分
- クリックしたマスの左右上下の取得方法をもっとスマートにできる気がした
- 「ヨコではさまれたら色変更」が、今は同じ処理を何度も書いてしまっているので関数にしてスッキリさせる。
#学んだこと(今後の予想なども)
文字列から数値にできるのは結構便利だなあと思った。
今回のように座標をクラスとして使用してもなんとかなったのは、文字列を数値に変換できたからなので笑
できなかったらまた別の方法に変更することになってたと思います。
同じように変数名を動的に作るためにevalがすごく役に立った。とはいえ、あまり推奨されていないようなので、今後使用を検討しようと思います。
縦ではさまれた時の、横の時と同じようにしてできそうなのでいいのですが、斜めが怖いなあ
ただ、やっぱり処理の流れを考えるのはすごく楽しいので今後も楽しみながら進めていきたいと思います。
恥ずかしいけど、ここまでのコードも貼っておこう
See the Pen reversi#01 by 谷口 (@taniguchi06) on CodePen.
最後まで読んでいただいたきありがとうございました。