Skip to content

Instantly share code, notes, and snippets.

@Konard
Last active March 22, 2023 02:39
Show Gist options
  • Save Konard/8937f6e6b34a0043cbdf9254765bb826 to your computer and use it in GitHub Desktop.
Save Konard/8937f6e6b34a0043cbdf9254765bb826 to your computer and use it in GitHub Desktop.

Write a tic-tac-toe game using React.js stateless components. Put everything into single html file. Output just the code for index.html.


Here's a simple tic-tac-toe game using React.js stateless components within a single HTML file. Simply copy and paste the following code into an index.html file and open it in a browser to see the game in action.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Tic Tac Toe - React.js Stateless Components</title>
    <style>
        .board-row {
            display: flex;
        }
        .square {
            width: 50px;
            height: 50px;
            border: 1px solid #000;
            text-align: center;
            line-height: 50px;
            font-size: 24px;
        }
    </style>
</head>
<body>
    <div id="root"></div>
    <script src="https://unpkg.com/react@17/umd/react.production.min.js"></script>
    <script src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js"></script>
    <script src="https://unpkg.com/[email protected]/babel.min.js"></script>
    <script type="text/babel">
        function Square(props) {
            return (
                <button className="square" onClick={props.onClick}>
                    {props.value}
                </button>
            );
        }

        function Board(props) {
            function renderSquare(i) {
                return (
                    <Square
                        value={props.squares[i]}
                        onClick={() => props.onClick(i)}
                    />
                );
            }

            return (
                <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>
            );
        }

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

        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

Continue.


";
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;
            if (winner) {
                status = "Winner: " + winner;
            } else {
                status = "Next player: " + (this.state.xIsNext ? "X" : "O");
            }

            return (
                <div className="game">
                    <div className="game-board">
                        <Board
                            squares={current.squares}
                            onClick={(i) => this.handleClick(i)}
                        />
                    </div>
                    <div className="game-info">
                        <div>{status}</div>
                        <ol>{moves}</ol>
                    </div>
                </div>
            );
        }
    }

    ReactDOM.render(<Game />, document.getElementById("root"));
</script>
</body>
</html>

This code snippet creates a single-page application with a tic-tac-toe game. It uses functional components for the Square and Board elements and a class-based component for the Game element. The game allows you to play moves, check the game state, and navigate through the move history.


Make code shorter.


I've condensed the code by removing some blank lines and shortening variable names. The functionality remains the same:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Tic Tac Toe - React.js Stateless Components</title>
    <style>
        .board-row { display: flex; }
        .square {
            width: 50px; height: 50px; border: 1px solid #000;
            text-align: center; line-height: 50px; font-size: 24px;
        }
    </style>
</head>
<body>
    <div id="root"></div>
    <script src="https://unpkg.com/react@17/umd/react.production.min.js"></script>
    <script src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js"></script>
    <script src="https://unpkg.com/[email protected]/babel.min.js"></script>
    <script type="text/babel">
        const Square = (p) => <button className="square" onClick={p.onClick}>{p.value}</button>;
        const Board = (p) => {
            const rs = (i) => <Square value={p.squares[i]} onClick={() => p.onClick(i)} />;
            return (
                <div>
                    <div className="board-row">{rs(0)}{rs(1)}{rs(2)}</div>
                    <div className="board-row">{rs(3)}{rs(4)}{rs(5)}</div>
                    <div className="board-row">{rs(6)}{rs(7)}{rs(8)}</div>
                </div>
            );
        };
        const calculateWinner = (sq) => {
            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 (sq[a] && sq[a] === sq[b] && sq[a] === sq[c]) return sq[a];
            }
            return null;
        };
        class Game extends React.Component {
            constructor(p) {
                super(p);
                this.state = { history: [{ squares: Array(9).fill(null) }], stepNumber: 0, xIsNext: true };
            }
            handleClick(i) {
                const h = this.state.history.slice(0, this.state.stepNumber + 1);
                const c = h[h.length - 1];
                const sq = c.squares.slice();
                if (calculateWinner(sq) || sq[i]) return;
                sq[i] = this.state.xIsNext ? "X" : "O";
                this.setState({ history: h.concat([{ squares: sq }]), stepNumber: h.length, xIsNext: !this.state.xIsNext });
            }
            jumpTo(step) { this.setState({ stepNumber: step, xIsNext: (step % 2) === 0 }); }
            render() {
                const h = this.state.history, c = h[this.state.stepNumber], w = calculateWinner(c.squares);
                const moves = h.map((step, move) => {
                    const desc = move ? 'Go to move #' + move : 'Go to game start';
                    return <li key={move

Continue.


}><button onClick={() => this.jumpTo(move)}>{desc}</button></li>;
});
const status = w ? "Winner: " + w : "Next player: " + (this.state.xIsNext ? "X" : "O");
return (
<div className="game">
<div className="game-board">
<Board squares={c.squares} onClick={(i) => this.handleClick(i)} />
</div>
<div className="game-info">
<div>{status}</div>
<ol>{moves}</ol>
</div>
</div>
);
}
}
ReactDOM.render(<Game />, document.getElementById("root"));
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Tic Tac Toe - React.js Stateless Components</title>
<style>
.board-row {
display: flex;
}
.square {
width: 50px;
height: 50px;
border: 1px solid #000;
text-align: center;
line-height: 50px;
font-size: 24px;
}
</style>
</head>
<body>
<div id="root"></div>
<script src="https://unpkg.com/react@17/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/[email protected]/babel.min.js"></script>
<script type="text/babel">
function Square(props) {
return (
<button className="square" onClick={props.onClick}>
{props.value}
</button>
);
}
function Board(props) {
function renderSquare(i) {
return (
<Square
value={props.squares[i]}
onClick={() => props.onClick(i)}
/>
);
}
return (
<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>
);
}
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;
}
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;
if (winner) {
status = "Winner: " + winner;
} else {
status = "Next player: " + (this.state.xIsNext ? "X" : "O");
}
return (
<div className="game">
<div className="game-board">
<Board
squares={current.squares}
onClick={(i) => this.handleClick(i)}
/>
</div>
<div className="game-info">
<div>{status}</div>
<ol>{moves}</ol>
</div>
</div>
);
}
}
ReactDOM.render(<Game />, document.getElementById("root"));
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment