【React】useStateを利用しゲーム作成 #3(ゲーム作成)

はじめに

useStateを利用して、ゲームを作成していきます。

ゲーム作成

ゲームルール

特定の数字を言ったら負けというゲームを作成していきます。
特定の数字を画面上より入力できるようにします。

その他ルール
・数字は0からスタート
・1ターンに3まで数字を増加することが可能(1以上増加すれば、ターン終了することが可能
・特定の数字が0いじょうであることを確認

コード

※本来はpropsのチェック等も可読性のためにも実施した方がいいです。

import classes from "../../scss/NumberGame.module.scss";
import { useState } from "react";

// プレイヤー名
const PLAYER = ["A", "B"];

/**
 * 現在のゲーム状況を表示
 * 数字増加、ターン終了ボタン
 *
 * @param  props
 * @returns jsx
 */
const GameArea = (props) => {
  if (props.status) {
    return (
      <div className={classes.game_area}>
        <p>{props.increaseCount}</p>
        <p>{props.turnPlayer}さんのターンです</p>
        <div className={classes.game_area_button}>
          <button
            onClick={() => {
              props.setIncreaseCount();
              props.setClickCount();
            }}
            disabled={props.clickCount === 3 || props.judge ? true : false}
          >
            数字を増加
          </button>
          <button
            onClick={() => {
              props.setClickCountZero();
              props.setTurnPlayer();
            }}
            disabled={props.clickCount === 0 || props.judge ? true : false}
          >
            ターン終了
          </button>
        </div>
      </div>
    );
  } else {
    return (
      <div>
        <p>ゲーム開始前です</p>
      </div>
    );
  }
};

/**
 * 勝敗がついた際に、負けた方を表示
 * @param props
 * @returns jsx
 */
const JudgeArea = (props) => {
  if (props.judge) {
    return (
      <div>
        <p>{props.turnPlayer}さんの負け</p>
      </div>
    );
  }
};

export const NumberGame = () => {
  // ゲームのスタート有無
  const [status, setStatus] = useState(false);
  // 特定の数字
  const [deadNumber, setDeadNumber] = useState(10);
  // 積み上げた数字
  const [increaseCount, setIncreaseCount] = useState(0);
  // どちらのターン
  const [turnPlayer, setTurnPlayer] = useState(PLAYER[0]);
  // 1ターンに増加した数
  const [clickCount, setClickCount] = useState(0);
  // paramの検証
  const [paramCheck, setParamCheck] = useState(false);
  // 勝敗判定
  const judge =
    Number(deadNumber) === Number(increaseCount) && Number(increaseCount) !== 0
      ? true
      : false;

  return (
    <div className={classes.main}>
      <div>
        <label for="input-dead-number">数字を入力してください:</label>
        <input
          id="input-dead-number"
          type="text"
          name="dead-number"
          maxLength="2"
          value={deadNumber}
          onChange={(e) => setDeadNumber(e.target.value)}
          disabled={status}
        />
        <button
          onClick={() => {
            if (deadNumber > 0) {
              setStatus(true);
              setParamCheck(false);
            } else {
              setParamCheck(true);
            }
          }}
          disabled={status}
        >
          ゲーム開始
        </button>
        {paramCheck && (
          <div className={classes.param_error}>
            <label>数字2桁以内で入力してください</label>
          </div>
        )}
      </div>
      <GameArea
        status={status}
        deadNumber={deadNumber}
        increaseCount={increaseCount}
        setIncreaseCount={() => setIncreaseCount(increaseCount + 1)}
        turnPlayer={turnPlayer}
        setTurnPlayer={() => {
          turnPlayer === PLAYER[0]
            ? setTurnPlayer(PLAYER[1])
            : setTurnPlayer(PLAYER[0]);
        }}
        clickCount={clickCount}
        setClickCount={() => setClickCount(clickCount + 1)}
        setClickCountZero={() => setClickCount(0)}
        judge={judge}
      />
      <JudgeArea judge={judge} turnPlayer={turnPlayer} />
      <div>
        <button
          onClick={() => {
            setStatus(false);
            setDeadNumber(10);
            setIncreaseCount(0);
            setClickCount(0);
            setTurnPlayer(PLAYER[0]);
          }}
        >
          リセット
        </button>
      </div>
    </div>
  );
};
.main {
  font-size: medium;
  padding: 10px;
  text-align: center;
}

.game_area_button {
  display: flex;
  align-items: center;
  justify-content: center;

  button {
    margin: 10px;
  }
}

.param_error {
  color: red;
}

stateとして以下を管理しています。この値が変更した際は再描画されます。
・ゲームの開始有無
  ゲーム開始した際は、ゲーム開始ボタンを押せないようにしています。
・特定の数字が0以上が入力されたかどうか
  0以上が入力されていない場合はエラー表示をするために利用しています。
・特定の数字
  言ったら負けとなる数字を管理しています。(デフォルトは10)
・増加している数字
  現状いくつまで数字が積み上がっているかを管理しています。
・どちらのターンか(定数でAとBというプレイヤーを用意)
  AとBどちらのプレイヤーかを判断しています。
・1ターンに増加した数
  1ターンに増回した数を管理し、1ターンに1以上3以下の数字を増加するように管理しています。

これらの値を更新する場合は「setXXX」の関数を利用しています。

動作確認

一覧画面から「特定の数字を言ったら負け」を選択すると画面遷移すること

0以上の数字を入力して「ゲーム開始」を選択するとエラーとなりゲームが始まらないこと

数字を20にして「ゲーム開始」を選択するとゲームが開始すること
開始後1以上3以下の値を増加すると「ターン終了」しプレイヤーが変わること

20を入力したプレイヤーが負けること

「リセット」を選択するとゲーム開始前の状態に戻ること

参考文献

useContext – React
The library for web and native user interfaces
タイトルとURLをコピーしました