美文网首页React
React 函数组件版井字棋 Tic Tac Toe

React 函数组件版井字棋 Tic Tac Toe

作者: Lia代码猪崽 | 来源:发表于2021-01-15 15:55 被阅读0次

文档地址

入门教程: 认识 React

完整代码

1. /src/App.js

import Game from "./components/Game";
import "./App.css";

function App() {
  return (
    <div className="App">
      <Game></Game>
    </div>
  );
}

export default App;

2. /src/components/Game/index.css

body {
  font: 14px "Century Gothic", Futura, sans-serif;
  margin: 20px;
}

ol, ul {
  padding-left: 30px;
}

.board-row:after {
  clear: both;
  content: "";
  display: table;
}

.status {
  margin-bottom: 10px;
}

.square {
  background: #fff;
  border: 1px solid #999;
  float: left;
  font-size: 24px;
  font-weight: bold;
  line-height: 34px;
  height: 34px;
  margin-right: -1px;
  margin-top: -1px;
  padding: 0;
  text-align: center;
  width: 34px;
}

.square:focus {
  outline: none;
}

.kbd-navigation .square:focus {
  background: #ddd;
}

.game {
  display: flex;
  flex-direction: row;
}

.game-info {
  margin-left: 20px;
}

3. /src/components/Game/index.js

import { useState, useMemo } from "react";
import "./index.css";

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

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

function Board({ squares, onClick }) {
  const rowSquares = useMemo(() => {
    return [squares.slice(0, 3), squares.slice(3, 6), squares.slice(6)];
  }, [squares]);

  return (
    <div>
      {rowSquares.map((row, rowIdx) => (
        <div key={rowIdx} className="board-row">
          {row.map((item, index) => {
            const i = rowIdx * 3 + index;
            const row = rowIdx + 1;
            const col = index + 1;
            return (
              <Square
                key={index}
                value={item}
                onClick={() => onClick(i, row, col)}
              ></Square>
            );
          })}
        </div>
      ))}
    </div>
  );
}

function Move({ step, move, onClick }) {
  const desc = move ? "Go to move #" + move : "Go to game start";
  return (
    <li style={{ textAlign: "left" }}>
      <button onClick={onClick}>{desc}</button>
      {step.row && (
        <>
          <span style={{ margin: "0 10px" }}>last position: </span>
          <span>
            row {step.row},col {step.col}
          </span>
        </>
      )}
    </li>
  );
}

function Game() {
  const [history, setHistory] = useState([
    {
      squares: Array(9).fill(null),
    },
  ]);
  const [stepNumber, setStepNumber] = useState(history.length);
  const [xIsNext, setXIsNext] = useState(true);
  const squares = useMemo(() => {
    return history[stepNumber - 1].squares;
  }, [history, stepNumber]);

  const winner = calculateWinner(squares);
  let status;
  if (winner) {
    status = "Winner: " + winner;
  } else {
    status = "Next player: " + (xIsNext ? "X" : "O");
  }

  function handleClick(i, row, col) {
    console.log(i, row, col);
    const tempSquares = [...squares];
    if (tempSquares[i] || winner) {
      return;
    }

    tempSquares[i] = xIsNext ? "O" : "X";

    const tempHistory = [
      ...history,
      {
        squares: tempSquares,
        row,
        col,
      },
    ];

    setHistory(tempHistory);
    setStepNumber(tempHistory.length);
    setXIsNext(!xIsNext);
  }
  function jumpTo(index) {
    setStepNumber(index + 1);
    setXIsNext(index % 2 === 0);
  }

  return (
    <div className="game">
      <div className="game-board">
        <Board
          squares={squares}
          onClick={(i, row, col) => handleClick(i, row, col)}
        />
      </div>
      <div className="game-info">
        <div>{status}</div>
        <ol>
          {history.map((item, index) => (
            <Move
              key={index}
              step={item}
              move={index}
              onClick={() => jumpTo(index)}
            ></Move>
          ))}
        </ol>
      </div>
    </div>
  );
}

export default Game;

相关文章

网友评论

    本文标题:React 函数组件版井字棋 Tic Tac Toe

    本文链接:https://www.haomeiwen.com/subject/xfqwoktx.html