개발 노트

React - tic tac toe 본문

Javascript

React - tic tac toe

Meter216 2023. 2. 24. 17:45

Square Component
class Square extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            value: null,
        };
    }
    render() {
        return (
            <button
                className="square"
                onClick={() => {
                    this.props.onClick();
                }}
                style={this.props.style} // style 형식 = {{background: "blue"}}
            >
                {this.props.value}
            </button>
        );
    }
}

트리의 제일 아래에 있는 Square 부분이다. 

Board 에서 부터 onClick과 style, value 값을 받아 부여해준다

** style 형식 = {{background: "blue"}}

 

 


Board Component

 

class Board extends React.Component {
    renderSquare(i) {
        const wincolor = this.props.winblock && this.props.winblock.indexOf(i) !== -1 ? { background: "blue" } : null;
        return <Square style={wincolor} value={this.props.squares[i]} onClick={() => this.props.onClick(i)} />;
    }

    render() {
        return (
            <div>
                {this.randerfor()}
                {/* <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>
        );
    }
}

return <Square style={wincolor} value={this.props.squares[i]} onClick={() => this.props.onClick(i)} />;

 

Square 이후는 태그속성이 아니다

==

this.props = {
style:wincolor
value:this.porps.squares[i]
onClick:this.props.onClick(i)
}

 

형태로 Square 로 props 로 넘겨준다.

 

 

 

render 부분의 하드코딩을 for문을 통해서 바꿀 수 있다.

  randerfor() {
        const square = [];
        for (let i = 0; i < 3; i++) {
            square.push(
                <div key={i} className="board-row">
                    {this.renderSquare(i * 3)}
                    {this.renderSquare(i * 3 + 1)}
                    {this.renderSquare(i * 3 + 2)}
                </div>
            );
        }
        return square;
    }

 


Game Component
class Game extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            history: [
                {
                    squares: Array(9).fill(null),
                },
            ],
            stepNumber: 0,
            xIsNext: true,
        };
    }

    handleClick(i) {
        const history = this.state.history.slice(0, this.state.stepNumber + 1);
        const current = history[history.length - 1];
        const squares = current.squares.slice();
        if (calculateWinner(squares) || squares[i]) {
            return;
        }
        squares[i] = this.state.xIsNext ? "X" : "O";
        this.setState({
            history: history.concat([{ squares: squares }]),
            stepNumber: history.length,
            xIsNext: !this.state.xIsNext,
        });
    }

    jumpTo(step) {
        this.setState({
            stepNumber: step,
            xIsNext: step % 2 === 0,
        });
    }

    render() {
        const history = this.state.history;
        const current = history[this.state.stepNumber];
        const winner = calculateWinner(current.squares);

        const moves = history.map((step, move) => {
            const desc = move ? "Go to move #" + move : "Go to game start";
            return (
                <li key={move}>
                    <button onClick={() => this.jumpTo(move)}>{desc}</button>
                </li>
            );
        });

        let status;
        let winblock;

        if (winner) {
            status = "Winner: " + winner.winner;
            winblock = winner.winIndex;
        } else if (current.squares.indexOf(null) === -1) {
            status = "DRAW";
        } else {
            status = "Next player: " + (this.state.xIsNext ? "X" : "O");
        }
        return (
            <div className="game">
                <div className="game-board">
                    <Board winblock={winblock} squares={current.squares} onClick={(i) => this.handleClick(i)} />
                </div>
                <div className="game-info">
                    <div>{status}</div>
                    <ol>{moves}</ol>
                </div>
            </div>
        );
    }
}


const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<Game />);

 

 

 

 

 

 

승리공식 코드

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],
    ];
    // 승리조건 array
    
    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]) {
            const winIndex = [a, b, c]; // 승리에 기여한 Index 값
            return { winner: squares[a], winIndex };  // 승리 value, index return 
        }
    }
    return null;
}
// ========================================

 

 

State 끌어올리기

 

Square에서 각기 다르게 선언되어있던 value 값을 Board로 모을 수 있다.

Board의 state에서 squares:ARRAY(9).fill(null) 만들어 준 후 
<Square value={this.state.squares[i]} />;

그려준다 Square 의 value 값은  Board state의 squares 값으로 변하게 되고 

 

이후 클릭 이벤트로 Board.state의 값이 변하고 다시 렌더가 되며 Square 의 상태값도 변화하며 다시 렌더가 된다.

Square 의 상태 = Board 의 state 값이 된다.

 

'Javascript' 카테고리의 다른 글

React 기본  (0) 2023.03.17
React 3.6 정리  (0) 2023.03.06
React  (0) 2023.02.23
Promise  (0) 2022.12.21
배열 메서드[join,map,filter,reduce]  (0) 2022.12.08