LoginSignup
3
0

More than 1 year has passed since last update.

Django+Reactで学ぶプログラミング基礎(24): Reactチュートリアル(ゲーム手番と勝者の判定)

Last updated at Posted at 2022-06-14
[前回] Django+Reactで学ぶプログラミング基礎(23): Reactチュートリアル(イミュータビリティ/関数コンポーネント)

はじめに

前回は、イミュータビリティの概念を勉強しました。
今回は、ゲームの残りを完成させます。

今回の内容

  • ゲームを完成させる
    • プレーヤーの手番を処理
    • ゲーム勝者を判定

プレーヤーの手番を処理

三目並べゲームで、相手プレーヤーOが盤面に出るように対応

  • プレーヤーの手番をxIsNext(真偽値)で表す
    • trueの場合はXの手番、falseの場合はOの手番
    • プレーヤーが着手するたびに、xIsNextが反転され、ゲームの状態が保存
  • デフォルトで、先手はX
    • Boardのコンストラクタでstateの初期値を変えることで、先手のデフォルトを変更可能
src/index.js
class Board extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      squares: Array(9).fill(null),
      xIsNext: true,
    };
  }
  • BoardhandleClick関数を書き換え、xIsNext値を反転させる
    • これで、X側とO側が交互に着手できるようになる
src/index.js
  handleClick(i) {
    const squares = this.state.squares.slice();
    squares[i] = this.state.xIsNext ? 'X' : 'O';
    this.setState({
      squares: squares,
      xIsNext: !this.state.xIsNext,
    });
  }
  • VS Codeで、アプリをデバッグ起動(F5)

    • 盤面をクリックし、X側とO側が交互に着手できることを確認
      image.png
  • Boardrender内にあるstatusテキストを変更し、次の手番を表示するように

src/index.js
render() {
    const status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O');

    return (
      // 残りの部分はそのまま
  • この時点で、Boardコンポーネントの全コード
src/index.js
class Board extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      squares: Array(9).fill(null),
      xIsNext: true,
    };
  }

  handleClick(i) {
    const squares = this.state.squares.slice();
    squares[i] = this.state.xIsNext ? 'X' : 'O';
    this.setState({
      squares: squares,
      xIsNext: !this.state.xIsNext,
    });
  }

  renderSquare(i) {
    return (
      <Square
        value={this.state.squares[i]}
        onClick={() => this.handleClick(i)}
      />
    );
  }

  render() {
    const status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O');

    return (
      <div>
        <div className="status">{status}</div>
        <div className="board-row">
          {this.renderSquare(0)}
          {this.renderSquare(1)}
          {this.renderSquare(2)}
        </div>
        <div className="board-row">
          {this.renderSquare(3)}
          {this.renderSquare(4)}
          {this.renderSquare(5)}
        </div>
        <div className="board-row">
          {this.renderSquare(6)}
          {this.renderSquare(7)}
          {this.renderSquare(8)}
        </div>
      </div>
    );
  }
}

ゲーム勝者の判定

  • 決着がついたか、次の手番がなくなったら、勝者を判定
    • ファイル末尾に以下のヘルパー関数をコピー
      • 9つのマス目を表すsquares配列が与えられたら、勝者がいるか判断し、X/O/nullを返す
      • 縦/横/斜めのいずれかで、同じマークが3つ並ぶと勝ち
src/index.js
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, b, c] = lines[i];
    if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
      return squares[a];
    }
  }
  return null;
}
  • Boardrender関数内でcalculateWinner(squares)を呼び出す
    • いずれかのプレーヤーが勝利したか否か判定
      • 決着がついた場合、Winner: XまたはWinner: Oを表示
    • Boardrender関数のstatus宣言を以下のコードで置き換える
src/index.js
render() {
    const winner = calculateWinner(this.state.squares);
    let status;
    if (winner) {
      status = 'Winner: ' + winner;
    } else {
      status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O');
    }

    return (
      // 残りのコードはそのまま

image.png

  • ゲームの決着がついた、またはマス目がすべて埋まった場合
    • 早期にreturnできるように、BoardhandleClickを書き換える
src/index.js
handleClick(i) {
    const squares = this.state.squares.slice();
    if (calculateWinner(squares) || squares[i]) {
      return;
    }
    squares[i] = this.state.xIsNext ? 'X' : 'O';
    this.setState({
      squares: squares,
      xIsNext: !this.state.xIsNext,
    });
  }

image.png

  • これで三目並べゲームが完成、おめでとうございます!
    • 例: Oが縦で三つ並び、Winner: Oと表示されました
      image.png

おわりに

ゲームアプリ構築を通じて、Reactの基本を学びました。
次回も続きます。お楽しみに。

[次回] Django+Reactで学ぶプログラミング基礎(25): Reactチュートリアル(タイムトラベル機能)
3
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
3
0