このページではソースコードの一部分を簡単な解説をしています。
コード全体はgithubにあります。
その他、作成したアプリやゲームの一覧はこちらにあります 。
概要
二人で遊べるオセロを作ってみました。実装した主な機能は以下の通りです。
- 盤面のマスの数を3種類の中から選択できる。(4×4・6×6・8×8)
- マスをクリック(タップ)すると石を置く。
- 石を同じ色で挟むと自動で裏返る。
- 黒と白の石の数を表示する。
- 石を置く場所が無いときは自動で手番をスキップする。
- お互いに石を置けなくなったらゲームを終了して結果を表示する。
ルールは黒が先手、白が後手となっています。終局時に、両者着手出来ない空きマスは勝者のものとして加算されます。
オセロの盤作成
オセロの盤面はテーブル要素で作成しました。
※以下からのコードは直接的に関係ない属性・変数名は省略しています。コード全体はgithubにあります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
let data = []; let cells = 4; // マスの数 const board = document.getElementById("board"); for (let i = 0; i < cells; i++) { const tr = document.createElement("tr"); data[i] = Array(cells).fill(0); for (let j = 0; j < cells; j++) { const td = document.createElement("td"); // オセロのマス const disk = document.createElement("div"); // オセロの石 tr.appendChild(td); td.appendChild(disk); } board.appendChild(tr); } |
盤面の管理はdata配列で管理しています。中身は2次元配列になっていて0は空いているマス、1は黒-1は白となっています。
1 2 3 4 5 6 7 |
// 4x4マスオセロの初期配置の例 data = [ [0, 0, 0, 0], [0, -1, 1, 0], [0, 1, -1, 0], [0, 0, 0, 0], ]; |
クリックされた位置の取得にはtd要素にonclick属性を設定し、parentNodeのrowIndexプロパティで縦の位置、cellIndexプロパティで横の位置を取得しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
td.onclick = clicked; // マスがクリックされた時の処理 function clicked() { let y = this.parentNode.rowIndex; let x = this.cellIndex; // マスに置けるかチェック if (data[y][x] !== 0) { return; } } |
クリックされたマスの周囲8方向を調べる
マスがクリックされたら石の周りに違う色の石があるかを調べます。(黒の手番でマスをクリックした時の例)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
// 周囲8方向を調べる配列 const direction = [ [-1, 0], // 左 [-1, 1], // 左下 [0, 1], // 下 [1, 1], // 右下 [1, 0], // 右 [1, -1], // 右上 [0, -1], // 上 [-1, -1], // 左上 ]; // 置いた石の周りに違う色の石があるかチェック for (let i = 0; i < direction.length; i++) { dx = direction[i][0] + x; dy = direction[i][1] + y; if ( // 盤面範囲いないか? dx >= 0 && dy >= 0 && dx <= cells - 1 && dy <= cells - 1 && // 色が違うか? WHITE === data[dy][dx] ) { // 石の周りに違う色があったら挟めるか調べる } } |
挟めるか調べる
石の周りに違う色があった場合はそのマスの先を調べます。(黒の手番でマスをクリックした時の例)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
let tmpReverseDisk = []; let reverseDisk = []; // 挟めるか調べる while (true) { dx += direction[i][0]; dy += direction[i][1]; if ( // 盤面範囲いないか・空のマスではないか dx < 0 || dy < 0 || dx > cells - 1 || dy > cells - 1 || data[dy][dx] === 0 ) { tmpReverseDisk = []; break; } // 白の石だった場合は座標を配列に仮保存してその先のマスを調べる if (WHITE === data[dy][dx]) { tmpReverseDisk.push([dx, dy]); } // 黒の石だった場合は挟んでいるので仮保存していた座標をすべてまとめる if (BLACK === data[dy][dx]) { reverseDisk = reverseDisk.concat(tmpReverseDisk); tmpReverseDisk = []; break; } } |
最後までお読みいただきありがとうございました。
コード全体はgithubにあります。
その他、作成したアプリやゲームの一覧はこちらにあります 。