CodeSandbox練功區 / Coding - 碼農筆記 / JavaScript / react

用React做井字遊戲

這個用React做井字遊戲練習是跟著 姚偉揚老師 在HiSKIO 裡 React 16 完全精通 – 從原理到大量實戰應用 的課程練習筆記,課程由淺入深,非常推薦想要學習 React 的人可以訂閱課程。

1. 先定義遊戲的九宮格在state中該如何呈現

0: 空白
1: 圈
-1:叉

state = {
  grids: [0, 0, 0, 0, 0, 0, 0, 0, 0],
  player: 1
};

2. 定義 toSymbol(使用switch) 來轉換呈現出來的UI畫面

const toSymbol = elm => {
  switch(elm) {
    case 0: return '';
    case 1: return 'o';
    case -1:
    defalut:
      return 'x'
  }
}

將每個格子用map 呈現出來

<div className={style.board}>
  {grids.map((elm, idx) => (
    <div className={style.grid}>
      <span>{toSymbol(elm)}</span>
    </div>
  ))}
</div>

3. 建立並定義九宮格樣式,引入Game.js中

import style from “./Game.module.css”;

* {
  box-sizing: border-box;
}
.board {
  width: 240px;
  height: 240px;
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  border: 1px solid #ddd;
}

.grid {
  width: 80px;
  border: 1px solid #ddd;
  display: flex;
  justify-content: center;
  align-items: center;
  cursor: pointer;
}

.grid span {
  font-size: 48px;
}

4. 點擊每個格子時,顯示代表的player

這裡的onClick 內要使用arrow function 才能取到當下點擊到的格子(idx)

<div key={idx} className={style.grid} onClick={() => this.handleClick(idx)}>
  <span>{toSymbol(elm)}</span>
</div>

傳入當下點擊到的格子位置(idx) ,並修改state裡的 grids 和 players,player的切換只需在state前加個”負號” 即可 (因為資料定義裡1表示o,-1表示x)

handleClick = idx => {
    const grids = [...this.state.grids];
    grids[idx] = this.state.player;
    this.setState({
      grids,
      player: -this.state.player
    });
  };

5. 建立清空按鈕

<button className={style.btn} onClick={this.reset}>
  Clear
</button>


  reset = () => {
    this.setState({
      grids: [0, 0, 0, 0, 0, 0, 0, 0, 0]
    });
  };

6. 判斷如果己點擊的格子不可再點擊

在 handleClick 裡加上 if 判斷式: if (grids[idx] !== 0) return;

handleClick = idx => {
    const grids = [...this.state.grids];
    if (grids[idx] !== 0) return;
    ...略
  };

7. 判斷是有已有連線

建立 lines 的陣列來表示九宮格裡的九個連線,毎個連線亦是一個陣列

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]
];

在每次更新時判斷上一個state的grid和現在的state的grid是否相同,如果不同則更新winner的state(跑 this.getWinner function),確認是否有贏家出現

componentDidUpdate(prevProps, prevState) {
    if (prevState.grids !== this.state.grids) {
      this.setState({
        winner: this.getWinner()
      });
    }
  }

建立 getWinner function

getWinner = () => {
    const { grids } = this.state;
    for (const line of lines) {
      const [i, j, k] = line;
      if (grids[i] === grids[j] && grids[j] === grids[k]) {
        return grids[i];
      }
    }
    return 0;
  };

判斷如有winner出現,則其他格子都不能再點擊 if (this.state.winner !== 0) return

handleClick = idx => {
    if (this.state.winner !== 0) return
    ...略

照著以上步驟就完成 React版的井字遊戲

© 2024 胡同筆記 | WordPress Theme: Cosimo by CrestaProject.