React로 Tic-React-Toe 게임을 만들어 봅시다!

React 여정을 시작했을 때 저는 Udemy에서 코스를 시작한 다음 YouTube에서 또 다른 코스를 시작한 다음 Coursera에서 또 다른 코스를 시작했습니다. 당신은 도전받지 않은 느낌을 시작합니다.

예, 코딩을 배우는 것은 정말 멋진 일이지만, 스스로 해보는 것은 꽤 두려운 일입니다. 그래서 비디오, 코스, 긴 튜토리얼(문서 제외)을 버리고 스스로 React를 코딩하기 위한 첫 번째 단계를 밟았습니다. 즉, 나만의 tic-tac-toe 게임을 만드는 것입니다.

Tic-Tac-Toe 게임은 이미 너무 과장되어 있지만 새로운 프로그래밍 언어를 배울 때 기본 사항 등을 가르쳐 주는 모든 것을 시도하는 것이 좋습니다. 연습은 완벽을 만들고, 완벽하지 않더라도 확실히 더 나아집니다.

이제 내 지식을 미래의 React Master와 공유하겠습니다! 😊

프로젝트에 대한 모든 설명은 주석을 통해 코드 자체에 있지만 막히거나 내 CSS 파일을 보려면 이미지 또는 사용자 지정 글꼴을 사용하고 내 GitHub Repository에서 확인하십시오.

만들기 전에 테스트하고 싶습니까? Heroku에서 테스트해 보십시오.

사전 설정 - 패키지 설치



이 프로젝트를 내가 한 것처럼(또는 원하는 대로) 완료하려면 선호하는 명령줄에서 다음을 수행해야 합니다.

npx create-react-app tic-tac-react
npm i react-bootstrap bootstrap --save
cd tic-tac-react


1단계 - 초기 설정



다음 구성 요소 파일을 포함하도록 App.JS 파일을 설정합니다. 즉, components , ./src , Board.js , Game.js 파일에 대해 Square.js 폴더에 Header.js 폴더를 만들 수 있습니다.

//App.js

import React from 'react';
import Game from './components/Game';
import Header from './components/Header';
import 'bootstrap/dist/css/bootstrap.min.css';

//Exports the App function to be used in index.js
function App() {
  return (
    <div className="App">
      <Header /> 
      <Game />
    </div>
  );
}
//Exports App Component to be used in index.js`
export default App;


2단계 - 사각형 만들기



나중에 만들 보드에서 값을 선택할 수 있으려면 먼저 "x"또는 "o"값을 포함할 사각형을 렌더링해야 합니다.
Square.js 파일에서 다음을 수행합니다.

//Square.js
import React from 'react';

//The Square component function a single <button>
function Square(props) {
    return (
      //onClick handler that will re-render the Square value whenever the <button> is clicked.
      <button className="square" onClick={props.onClick}>
        {/* this will call the value passed by the renderSquare component into the square, x or o*/}
        {props.value}
      </button>
    );
  }

//Exports Square Component to be used in app.js
export default Square;


3단계 - 보드 만들기



이제 보드는 게임에 대한 기본 인터페이스가 될 것이며 다음 단계에서 작동하도록 만들 것입니다. 이제 게임 보드에 생성된 사각형 버튼을 렌더링해야 합니다.
Board.js 파일에서 다음을 수행합니다.

//Board.js
import React from 'react';
import Square from './Square';
import {Container, Row} from 'react-bootstrap';

//Board renders 9 squares to compose the tic-tac-toe board
class Board extends React.Component {

    //Pass the props to render the square number value to the board
      renderSquare(i) {
        /* this will pass a value (x, o, or null) to the Square */
        return (
          <Square 
            value={this.props.squares[i]}
            onClick={() => this.props.onClick(i)}
          />
        );
      }

    //Board rendering with square value init
    render() {
      //this will set the render the board
      return (
        <Container>
          <Row>
              <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>
          </Row>
        </Container>

      );
    };
  }

//Exports Board Component to be used in app.js
export default Board;


4단계 - 최종 게임 만들기



이제 보드와 사각형을 만들었으므로 실제 게임에 기능을 추가해야 합니다.
Game.js 파일에서 다음을 수행합니다.

//Game.js
import React from 'react';
import Board from './Board';
import {Button, Container, Row, Col} from 'react-bootstrap';

//The Game component renders a board which adds functionality to the game
class Game extends React.Component {
    constructor(props) {
      super(props);
      this.state = {
        //sets the Board's initial state to contain an array of 9 nulls on 9 squares
        history: [{
          squares: Array(9).fill(null),
        }],
        //Indicates which step we’re currently viewing.
        stepNumber: 0,
        //xIsNext (a boolean) will be flipped to determine which player goes next and the game’s state will be saved
        xIsNext: true,
      }     
    }

    //sets the state of the clicked square to an X value
    handleClick(i) {
      //ensures we don’t get stuck showing the same move after a new one has been made.
      const history = this.state.history.slice(0, this.state.stepNumber + 1);
      const current = history[history.length - 1];
      const squares = current.squares.slice();
      //returns early by ignoring a click if someone has won the game or if a Square is already filled:
      if (calculateWinner(squares) || squares[i]) {
        return;
      }
      squares[i] = this.state.xIsNext ? 'X' : 'O';
      //will either set the state of the clicked block to be x, or negate it to o
      this.setState ({
        history: history.concat([{
          squares: squares
        }]),
        stepNumber: history.length,
        xIsNext: !this.state.xIsNext
      });
    }

    //update that stepNumber to its current step and that the number of the step is even
    jumpTo(step) {
      this.setState({
        stepNumber: step,
        xIsNext: (step % 2) === 0,
      })
    }

    render() {
      // uses the most recent history entry to determine and display the game’s status
      const history = this.state.history;
      const current = history[this.state.stepNumber];
      const winner = calculateWinner(current.squares);

      //For each move in the tic-tac-toe game’s history, we create a list item <li> which contains a button <button>.
      const moves = history.map((step, move) => {
        //display the current move and history upon click
        const desc = move ? 
        'Return To Move #' + move :
        'Reset Game Board ';
        return (
          //we assign a key to the move list to make each move unique so it cannot be re-ordered, deleted or inserted
          <li key={move}>
             <Button className="btn-prim" size="lg" onClick={() => this.jumpTo(move)}>{desc}</Button>
          </li>
        );
      });

      let status;
      if (winner) {
        status = 'Congrats! The winner is: ' + winner;
      } else {
        status = 'Player Turn: ' + (this.state.xIsNext ? 'X' : 'O');
      }

      return (
        <Container>
          <Row className="col-12">
            <div className="game-space"></div>
          </Row>
          <Row className="col-12">
            <div className="game">
              <Col className="col-12 col-md-6 col-lg-6"> 
                    <div className="game-board">
                      <Board 
                        squares={current.squares} 
                        onClick={i => this.handleClick(i)}
                      />
                    </div>
              </Col>
              <Col className="col-12 col-md-6 col-lg-6"> 
              <div className="game-info">
                  <div className="game-status">{status}</div>
                  <ol className="game-moves">{moves}</ol>
                </div>
              </Col>   
          </div>
          </Row>
        </Container>    
      );
    }
  }

  //This will calculate the winner of the game after all possible moves are used
function calculateWinner(squares) {
    //possible winning moves for array of 9 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],
    ];
    //Given an array of 9 squares, this function will check for a winner and return 'X', 'O', or null as appropriate.
    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;
  };

//Exports Game Component to be used in app.js
export default Game;


5단계 - 최종 수정



이제 완전히 선택 사항인 헤더 파일을 추가할 수 있지만 기능적 구성 요소에서 레이아웃 파일을 분리하는 것을 선호합니다.

이것을/components 폴더에 넣는 대신 /layout라는 새 폴더를 만들고 거기에 Header.js를 저장할 수도 있습니다.

//Header.js
import React from 'react';
import {Container, Row} from 'react-bootstrap';

//The Header component which will be main ui of game
function Header() {
    return (
        <Container>
            <Row>
                <div className="Header">
                    <h4 className="pre-title">WELCOME TO</h4>
                    <h1 className="game-title">Tic Tac React!</h1>
                </div>
            </Row>
            <Row> </Row>
        </Container>
    );
  }

//Exports Header Component to be used in app.js
export default Header;


6단계 - CSS 및 배포!



수고하셨습니다. 튜토리얼을 완료했습니다. 이제 다음 명령으로 게임을 테스트할 수 있습니다.

npm start


응용 프로그램에 일부 CSS 또는 스타일을 추가하는 것을 잊지 마십시오. 그렇지 않으면 확실한 uggo입니다. 위에 나열된 내 GitHub 저장소에서 내 CSS 파일에 대해 내가 수행한 작업을 볼 수 있습니다.

최종 프로젝트는 다음과 같아야 합니다.



내가 말했듯이, 나는 React 전문가는 아니지만 오늘 뭔가 새롭고/다른 것을 보여줄 수 있기를 바랍니다! 저에게 알려주시거나 새로운 것을 가르쳐주세요. 댓글로 여러분의 의견을 듣고 싶습니다.😊

좋은 웹페이지 즐겨찾기