티스토리 뷰

React

[React] 틱택토 게임 구현

ljy98 2022. 4. 17. 17:20

1. 틱택토 게임 소개

2. 코드 구현


1. 틱택토 게임 소개

[그림 1] 구글에 틱택토 게임을 검색했을 때 나타나는 모습

틱택토(tic-tac-toe)는 두 명이 번갈아가며 O와 X를 3x3 판에 써서 같은 글자를 가로, 세로, 혹은 대각선 상에 놓이도록 하는 놀이이다. 이번 글에서는 틱택토 게임을 진행할 수 있게 구현하고, 게임이 끝난 시점에서 승자를 결정하는 것과 다음 플레이어가 누구인지에 대해서도 나타내고자 한다.

 

 

2. 코드 구현

<div id="root"></div>
<script type="text/babel">
    const calculateWinner = (squares) => {
        const lines = [
            [0,1,2],
            [3,4,5],
            [6,7,8],
            [2,4,6],
            [0,4,8],
            [0,3,6],
            [1,4,7],
            [2,5,8]
        ];
        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
    };
    class Square extends React.Component{
        render() {
            return(<button className="square" onClick={this.props.onClick}>
                        {this.props.value}
                </button>)
        }
    };
    class Board extends React.Component{
        state = {
            squares:Array(9).fill(null),
            xIsNext:true
        };
        handleClick = (i) => {
            const squares = [...this.state.squares];
            calculateWinner(squares);
            if (squares[i] !== null || calculateWinner(squares) !== null) {
                return
            }
            const xIsNext = this.state.xIsNext;
            squares[i] = xIsNext ? 'X' : 'O';
            this.setState({
                ...this.state,
                squares,
                xIsNext:!xIsNext
            });
        };
        renderSquare = (i) => {
            return (<Square value={this.state.squares[i]} onClick={ () => {this.handleClick(i)} }/>)
        };  
        render() {
            const {renderSquare, state:{squares}} = this;
            const winner = calculateWinner(squares);
            const status = winner !== null ? `Winner: ${winner}` : `Next Player: ${this.state.xIsNext ? 'X' : 'O'}`;
            return(<div>
                        <div className="status">{status}</div>
                        <div className="board-row">
                            {renderSquare(0)}
                            {renderSquare(1)}
                            {renderSquare(2)}
                        </div>
                        <div className="board-row">
                            {renderSquare(3)}
                            {renderSquare(4)}
                            {renderSquare(5)}
                        </div>
                        <div className="board-row">
                            {renderSquare(6)}
                            {renderSquare(7)}
                            {renderSquare(8)}
                        </div>
                </div>)
        }
    };
    class Game extends React.Component{
        render() {
            return(<div className="game">
                        <div className="game-board">
                            <Board/>
                        </div>
                        <div className="game-info"></div>
                </div>)
        }
    };
    ReactDOM.render(
        <Game/>,
        document.querySelector('#root')
    );
</script>

calculateWinner 함수는 게임 진행 중 승자가 발생하는 시점을 정한다. 승자가 되기 위해서는 lines라는 이중 배열의 원소 [0,1,2] 부터 [2,5,8] 까지 총 8가지 경우 중 하나를 상대방보다 먼저 만족시켜야 한다.

 

Square 컴포넌트 3x3 판의 각각의 사각형에 해당한다. <button> 태그를 클릭했을 때 this.props.onClick 이 실행되는데, 이것은 Board 컴포넌트의 renderSquare 함수의 onClick={ () => this.handleClick(i)}에 있는 handleClick 함수를 말한다.

 

<button> 태그 내부의 {this.props.value} 또한 상위 컴포넌트인 Board의 renderSquare 함수의 value={this.state.squares[i]}의 value를 나타낸다.

 

Board 컴포넌의 state를 살펴보면, squares 속성이 Array(9), fill(null) 이라고 되어있는데, 이는 [null, null, null, null, null, null, null, null, null]과 같다. xIsNext는 다음 진행자가 O인지 X인지 구별하기 위한 속성으로 초기 속성 값은 true이다. 

 

handleClick 함수에서는 먼저 calculateWinner함수를 실행하고 해당 square의 값이 null이 아니거나 calculateWinner 함수 실행 값이 null이 아닐 때 return으로 함수를 빠져나온다. 즉, 이미 클릭한 곳을 또 클릭하거나 승자가 발생했을 경우에는 if 문 안의 return으로 빠져나오는 것이다. 그 외의 경우에는 xIsNext 값이 true였다면 false로, false였다면 true로 바뀌고 화면에는 X 또는 O가 나타난다.

 

Board 컴포넌트의 render() 안의 status는 winner가 있을 때에는 Winner : O (또는 X)가 되고, winner가 없을 때에는 Next Player : O (또는 X)가 되는 것을 삼항연산자로 나타낸 것이다.

 

[그림 2] 승자 발생 시

 

[그림 3] 다음 플레이어

위의 코드를 기반으로 브라우저에서 실행해보면 틱택토 게임을 제대로 플레이할 수 있고, 다음 플레이어와 승자가 누군지도 알 수 있다.

'React' 카테고리의 다른 글

[React] css 적용하기  (0) 2022.04.20
[React] 구구단 게임  (0) 2022.04.20
webpack 소개 및 사용 방법  (0) 2022.04.20
[React] props & state  (0) 2022.04.13
React 소개  (0) 2022.04.12
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
글 보관함