入門」シリーズ第3回は、いよいよゲームとして成り立たせます。XとOを交互につけ、勝ち負けを決めるということです。XとOを交互に描くXとOは交互につけなければなりません。つぎがXかどうかかを、クラスAppのstateにプロパティ(xIsNext)でブール(論理)値としてもたせます。そのうえで、マス目クリックのハンドラ(handleClick())で、加える文字を切り替えればよいでしょう。つぎの番がどちらかを、render()メソッドに書き加えてテキストで示すようにしました(図001)。className="game-info"><div>{status}</div></div></div>);}}ただこのままでは、つけてあった印が書き替えられてしまいます。マス目に印がすでにあったら、処理を進めないようにしなければなりません。勝ちを調べるいよいよ、どちらが勝ったか調べる関数(calculateWinner())を定めます。引数(squares)は、印の配置を要素にした配列です。関数本体では、勝ちの3マスの並びのインデックスが収められた配列8つを、予め変数(lines)の配列にもっておきます。揃った並びがあるかforループで調べて、あれば戻り値は勝ちの印(player)です。なければnullが返されます。null;}クラスAppのstateに新たに加えるのは、勝ちが決まったかどうかをブール値で示すプロパティ(finished)です。マス目をクリックしたら(handleClick())、今定めた関数(calculateWinner())で勝ちを調べます。勝者が決まったら、プロパティをtrueにしてゲームは終わりです。true});return;}};}勝者をテキストで示すように、render()メソッドもつぎのように書き替えましょう(図002)。'O');}}図002■勝者が決まるとテキストで示される無駄な処理を断捨離するクラスAppには勝負決着のプロパティ(finished)を設けて、クリックイベントのハンドラメソッド(handleClick())は、勝負が着いた処理は進めないようにしました。React公式サイトのチュートリアル作例には、このプロパティがありません。マス目をクリックするたびに、勝者判定の関数(calculateWinner())が呼び出されてしまうのです。重い処理ではないものの、無駄は省くに越したことはないでしょう。考えると、勝負がつかないまま9つのマス目が埋まった場合も、決着のプロパティを設定した方がよさそうです。次回このゲームにはさらに機能を加えます。断捨離は、そのあとまとめて行うつもりです。書き上がったモジュールsrc/components/App.jsのスクリプト全体は、つぎのコード001にまとめたとおりです。CodeSandboxに以下のサンプル001を掲げました。