LoginSignup
0
0

React入門8: テキストの実装

Last updated at Posted at 2023-12-09

はじめに

私自身の復習兼、備忘録的な意味もあり、複数回の記事に渡って React を用いてマルバツゲーム(三目並べ)を開発していきたいと思います。

シリーズの一覧

  1. React入門1: 環境構築 [オンライン版]
  2. React入門2: 盤面の作成
  3. React入門3: インタラクションの実装
  4. React入門4: リファクタリング [リフトアップ編]
  5. React入門5: リファクタリング [インタラクション編]
  6. React入門6: 手番の実装
  7. React入門7: ゲームの勝利判定
  8. React入門8: テキストの実装 (今回)
  9. React入門9: タイムトラベル(1)
  10. React入門10: タイムトラベル(2)
  11. React入門11: タイムトラベル(3)

目的について

全体の目的

React公式のチュートリアルで公開されているマルバツゲームを 3x3 のマスで実装していきます。

今回の目的

ゲームの状況を示すテキストを実装していきます。また、前回作成した calculateWinner() 関数を使って、決着がついた場合の勝者も表示できるようにします。

テキストの実装

次のページで、前回のソースファイルを確認できます。

  • 前回の内容はコチラから!

テキストの表示

App.js の Board コンポーネントの return 文に <div> 要素を加えて、盤面の上にテキストを表示させてみましょう。次の要件を満たすようにコーディングをしてみます。

  • 盤面の上に文字を表示するには return 文のどこに <div> 要素を加えればよいか
  • ゲームの状況 」というテキストを表示する
App.js の Board コンポーネント
export default function Board() {

  /* 省略 */

  return (
    <>
      <div>ゲームの状況</div>
      <div className="board-row">
        <Square value={squares[0]} onSquareClick={() => handleClick(0)} />
        <Square value={squares[1]} onSquareClick={() => handleClick(1)} />
        <Square value={squares[2]} onSquareClick={() => handleClick(2)} />
      </div>
      <div className="board-row">
        <Square value={squares[3]} onSquareClick={() => handleClick(3)} />
        <Square value={squares[4]} onSquareClick={() => handleClick(4)} />
        <Square value={squares[5]} onSquareClick={() => handleClick(5)} />
      </div>
      <div className="board-row">
        <Square value={squares[6]} onSquareClick={() => handleClick(6)} />
        <Square value={squares[7]} onSquareClick={() => handleClick(7)} />
        <Square value={squares[8]} onSquareClick={() => handleClick(8)} />
      </div>
    </>
  );
}

次に動作結果を示します。これで盤面の上に「ゲームの状況」というテキストを表示できるようになりました。

image.png

手番の表示

テキストで現在のプレイヤーが「X」と「O」のどちらであるかを表示していきます。

第6回の記事 で定義した、手番を管理している state 型の xIsNext 変数を使って、現在のプレイヤーを取得しましょう。この変数は、true のときに「X」、false のときに「O」のプレイヤーを表しています。

従って、テキスト( status 変数)を次のように制御すれば、操作中しているプレイヤーを示すことができます。

手番を表示するテキストの制御
  let status = "プレイヤー: ";

  if (xIsNext) {
    status += "X";
  } else {
    status += "O";
  }

では、App.js の Board() コンポーネントに次の変更を加えましょう。

  • 手番を表示するテキストの制御するプログラムを実装する
    • ゲームの状況を文字列で示す status 変数を宣言する
    • status 変数の内容を手番 (xIsNext 変数) に応じて更新する
  • return 文にある <div> 要素で手番を表示させる
App.js の Board コンポーネント
export default function Board() {
  /* 省略 */
  let status = "プレイヤー: ";

  if (xIsNext) {
    status += "X";
  } else {
    status += "O";
  }

  return (
    <>
      <div>{status}</div>

      <div className="board-row">
      /* 省略 */
      </div>
    </>
  );

動作結果を次に示します。これで、空白のマスをクリックした後に、テキストが変更されるようになりました。

output_video.gif

条件 (三項) 演算子の利用

JavaScriptの文法的な内容になります。動作結果に関する変更はないので、勝者の表示 まで飛ばしても大丈夫です。

先ほどのコードを、条件 (三項) 演算子を用いることで短くまとめていきます。まずは、見慣れた if-else 文の構文を示します。

if-else 文
if (条件) {
  真のときに実行する処理;
} else {
  偽のときに実行する処理;
}

これを条件 (三項) 演算子によって表現すると次の構文になります。

条件 ? 真のときに返す値 : 偽のときに返す値;

詳しい内容を調べたい方は次のリファレンスをご確認ください。

従って、手番を表示するテキストの制御は、次のようなコードで表すことができます。

手番を表示するテキストの制御 (簡略後)
  let status = "プレイヤー: " + (xIsNext ? "X" : "O");

余談ですが、このようにコードを省略することをショートハンドというみたいです。

勝者の表示

ゲームの決着がついたときに勝者を表示できるようにしていきます。App.js の Board コンポーネントに次の変更を加えましょう。

  • 勝者を示す winner 変数を宣言する
    • 初期値を勝利判定 (calculateWinner() 関数) の結果とする
  • 勝利判定の結果に応じてテキストの内容を変更する
    • 勝者がいる場合は、その印を表示する
      • 「X」が勝ったとき、「勝者: X」
      • 「O」が勝ったとき、「勝者: O」
    • 勝者が決まっていない場合は、次のプレイヤーを表示する
App.js
import { useState } from "react";
import "./styles.css";

function Square({ value, onSquareClick }) {
  return (
    <button className="square" onClick={onSquareClick}>
      {value}
    </button>
  );
}

export default function Board() {
  const [squares, setSquares] = useState(Array(9).fill(null));
  const [xIsNext, setXIsNext] = useState(true);

  const winner = calculateWinner(squares);
  let status;

  if (winner) {
    status = "勝者: " + winner;
  } else {
    status = "プレイヤー: " + (xIsNext ? "X" : "O");
  }

  function handleClick(i) {
    if (squares[i]) {
      return;
    }

    const nextSquares = squares.slice();

    if (xIsNext) {
      nextSquares[i] = "X";
    } else {
      nextSquares[i] = "O";
    }
    setSquares(nextSquares);
    setXIsNext(!xIsNext);
  }

  return (
    <>
      <div>{status}</div>
      <div className="board-row">
        <Square value={squares[0]} onSquareClick={() => handleClick(0)} />
        <Square value={squares[1]} onSquareClick={() => handleClick(1)} />
        <Square value={squares[2]} onSquareClick={() => handleClick(2)} />
      </div>
      <div className="board-row">
        <Square value={squares[3]} onSquareClick={() => handleClick(3)} />
        <Square value={squares[4]} onSquareClick={() => handleClick(4)} />
        <Square value={squares[5]} onSquareClick={() => handleClick(5)} />
      </div>
      <div className="board-row">
        <Square value={squares[6]} onSquareClick={() => handleClick(6)} />
        <Square value={squares[7]} onSquareClick={() => handleClick(7)} />
        <Square value={squares[8]} onSquareClick={() => handleClick(8)} />
      </div>
    </>
  );
}

function calculateWinner(squares) {
  const lines = [
    [0, 1, 2],
    [3, 4, 5],
    [6, 7, 8],
    [0, 3, 6],
    [1, 4, 7],
    [2, 5, 8],
    [0, 4, 8],
    [2, 4, 6],
  ];

  for (let i = 0; i < lines.length; i++) {
    const a = lines[i][0];
    const b = lines[i][1];
    const c = lines[i][2];

    if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
      return squares[a];
    }
  }
  return null;
}

動作結果を次に示します。これで、操作するプレイヤーだけでなく、勝者も表示できるようになりました。

勝者の判定.gif

これでゲームのシステムは完成しました!

おわりに

今回は、ゲームの状況を示すテキストを実装しました。これによって、マルバツゲームの主要な機能は完成です!お疲れ様でした。次のページにソースファイルを示します。

今後について
ここまで、マルバツゲームを開発していきましたが、まだまだ機能を追加する余地があります。例えば、公式チュートリアルにはまだ続きがあり、過去の手番に戻すタイムトラベル機能について解説されています。ご興味がある方は、上記のソースファイルを改変して次のページをご参照ください。(筆者の方でも記事にまとめるかもしれません... ← 9回目以降の記事にまとめました)

チュートリアル:三目並べ – React [タイムトラベルの追加]

次回以降から、ゲームにタイムトラベルの機能を追加していきます。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0