実際に動いているものはこちらで試すことが出来ます。
https://reversi-d1kqojbar.now.sh/
ゲームのルールを実装するには、大まかに分けて次の4つの処理が必要になります。
- 「次に石を配置可能な場所」の判定と表示
- 挟まれた石を裏返す
- 石を置ける場所が無い場合の「パス」処理
- ゲーム終了判定と勝敗の表示
1. 「次に石を配置可能な場所」の判定と表示
各手番が始まったときに、ボード上の全てのCellをループして次の処理を行います。
- 現在のCellからタテ・ヨコ・ナナメ全ての方向に向かってひとつずつ次のCellの色を確認する。
- 相手の石が置かれていたら、一時的な配列(arr)にそのCellの座標をプッシュして、さらにその方向の次のCellを確認。
- 自分の石が置かれていたら、その方向への探索を終了。
- 空白なら、その方向への探索を終了。
- 座標がボードの範囲外に出た場合は、その方向への探索を終了。
- 上の処理で最後に自分の石が見つかった場合で、かつ配列arrに要素が含まれている場合は、「挟める対象の相手の石が見つかった」ということなので、そのCellを「自分の石を配置可能なCell」としてマークしておく。(cell.placeableプロパティにtrueをセットする。)
Cellコンポーネントでは、対応するCellオブジェクトのplaceableプロパティが属性として渡されてくるので、その値がtrueの場合は、小さな黄色の円をSVGのcircleタグを使って表示するようになっています。
2. 挟まれた石を裏返す
プレーヤーがCellをクリックしたときには、CellコンポーネントのhandleClick()メソッドが実行され、さらにstoreのsetStone()メソッドにクリックされたCellの座標が渡されます。
store側では、Cellのplaceableプロパティがtrueでない場合は、そこには石を配置出来ないので何もせずにreturnしています。
そうでない場合は、クリックされた場所およびそこを起点として裏返し対象になるCellのcolorプロパティを全てプレーヤーの石と同じ色に変更します。
「裏返し対象のCell」というのは、あらかじめ上の「次に石を配置可能な場所」の判定処理の中で見つかったCellの座標一覧をcell.turnableCellsというプロパティに格納してあるので、それをループすることで取得できます。
裏返し対象のCellのcolorプロパティを全て変更する処理が終わった後、getNextTurn()メソッドを呼んで次のプレーヤーに手番を交替しています。
最後に'board_changed'イベントを発行して、各コンポーネントの描画を更新しています。
3. 石を置ける場所が無い場合の「パス」処理
現在の手番で石を置ける場所が見つからない場合は、ボードの placeableCount プロパティが 0 になります。
その場合は、ひとまず alert()でメッセージを表示した後、storeのskipTurn()メソッドを呼んで手番を「パス」します。
この処理はゲームの進行に関わる処理なので、Gameコンポーネント内で行っています。
skipTurn()メソッドの中では、ボードの状態を変更せずに、単に現在の手番を示す turn プロパティを更新して'board_changed'イベントを発行しています。
4. ゲーム終了判定と勝敗の表示
Gameコンポーネントでstoreから'board_changed'イベントを受け取った時に、finishedプロパティがtrueであればゲーム終了なのでその旨をalert()で表示します。
finishedプロパティがtrueになる条件は、以下の通りです。
- 空白のCellが無くなった。
- 黒または白のどちらかが全滅した。
- 両者とも置く場所が無くなった。
ボードの状態を更新する際にこのいずれかに当てはまるかどうかを毎回チェックしてfinishedプロパティの値をセットしています。
以上でリバーシのルールを実装して実際に遊べる状態にまで持って行くことが出来ました。
次回は、コンピュータの思考ルーチンを作成してコンピュータとの対戦機能を追加したいと思います!
今回の時点でのソースコードはこちら:
https://github.com/mikehibm/reversi-react/tree/blog-2
React/TypeScriptでリバーシゲームを作る
(1) - ボードの描画と石の配置
https://blog.makotoishida.com/2018/10/reacttypescript.html
(2) - ゲームロジック
https://blog.makotoishida.com/2018/11/reacttypescript-2.html
https://blog.makotoishida.com/2019/01/reacttypescript-3-1.html
(4) - 思考ルーチンその2
https://blog.makotoishida.com/2019/03/reacttypescript-3-2.html
(5) - アニメーション
https://blog.makotoishida.com/2019/03/reacttypescript-5.html