[react] Tic-Tac-Toe

ChanSol Jeong·2023년 8월 14일

react

목록 보기
7/13
post-thumbnail

react 튜토리얼 중에 가장 유명한 Tic-Tac-Toe를 만들면서 실습을 해보았다.

// index.js
const render = () => {
  const element = (
    <div>
      <TicTacToc></TicTacToc>
    </div>
  );
  root.render(element);
};

render();
// TicTacToc.js
import { useState } from "react";
import Board from "./Board";

export default function TicTacToc() {
  const [history, setHistory] = useState([Array(9).fill(null)]);
  const [currentMove, setCurrentMove] = useState(0);
  const xIsNext = currentMove % 2 === 0;
  const currentSquares = history[currentMove];

  const handlePlay = (nextSquares) => {
    const nextHistory = [...history.slice(0, currentMove + 1), nextSquares];
    setHistory(nextHistory);
    setCurrentMove(nextHistory.length - 1);
  }

  function jumpTo(nextMove) {
    setCurrentMove(nextMove);
  }

  const moves = history.map((squares, move) => {
    let description;
    if (move > 0) {
      description = 'Go to move #' + move;
    } else {
      description = 'Go to game start';
    }
    return (
      <li key={move}>
        <button onClick={() => jumpTo(move)}>{description}</button>
      </li>
    );
  });

  return (
    <div className="game">
      <div className="game-board">
        <Board xIsNext={xIsNext} squares={currentSquares} onPlay={handlePlay} />
      </div>
      <div className="game-info">
      <ol>{moves}</ol>
      </div>
    </div>
  );
}
import Square from "./Square";

export default function Board({ xIsNext, squares, onPlay }) {
  const handleClick = (i) => {
    if (calculateWinner(squares) || squares[i]) {
      return;
    }
    const nextSquares = squares.slice();
    if (xIsNext) {
      nextSquares[i] = "X";
    } else {
      nextSquares[i] = "O";
    }
    onPlay(nextSquares);
  }

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

  const winner = calculateWinner(squares);
  let status;
  if (winner) {
    status = "Winner: " + winner;
  } else {
    status = "Next player: " + (xIsNext ? "X" : "O");
  }
  return (<>
    <div className="status">{status}</div>
    <div className="board-row">
      <Square value={squares[0]} onSquareClick={() => handleClick(0)}></Square>
      <Square value={squares[1]} onSquareClick={() => handleClick(1)}></Square>
      <Square value={squares[2]} onSquareClick={() => handleClick(2)}></Square>
    </div>
    <div className="board-row">
      <Square value={squares[3]} onSquareClick={() => handleClick(3)}></Square>
      <Square value={squares[4]} onSquareClick={() => handleClick(4)}></Square>
      <Square value={squares[5]} onSquareClick={() => handleClick(5)}></Square>
    </div>
    <div className="board-row">
      <Square value={squares[6]} onSquareClick={() => handleClick(6)}></Square>
      <Square value={squares[7]} onSquareClick={() => handleClick(7)}></Square>
      <Square value={squares[8]} onSquareClick={() => handleClick(8)}></Square>
    </div>
  </>)
}
export default function Square({ value, onSquareClick }) {
  return (
    <button className="square" onClick={onSquareClick}>{value}</button>)
}

다 만들고나니깐 맨 아래에 5가지의 개선사항에 도전해보라는 말이 있었다.

1.For the current move only, show “You are at move #…” instead of a button.

2.Rewrite Board to use two loops to make the squares instead of hardcoding them.

3.Add a toggle button that lets you sort the moves in either ascending or descending order.

4.When someone wins, highlight the three squares that caused the win (and when no one wins, display a message about the result being a draw).

5.Display the location for each move in the format (row, col) in the move history list.

5가지의 개선사항에 대해서 수정해보며, 똑같은 게임을 vuecomposition API로도 한번 구현해봐야겠다.

profile
Compostion API 맛있다!

1개의 댓글

comment-user-thumbnail
2023년 8월 14일

잘 봤습니다. 좋은 글 감사합니다.

답글 달기