用 React18 构建Tic-Tac-Toe(井字棋)游戏

下面是一个完整的 Tic-Tac-Toe(井字棋)游戏的实现,用 React 构建。包括核心逻辑和组件分离,支持两人对战。

1. 初始化 React 项目:

bash 复制代码
npx create-react-app tic-tac-toe
cd tic-tac-toe

2.文件结构

scss 复制代码
src/
├── App.js
├── Board.js
├── Square.js
└── index.js

Step 1: Square.js - 单个方块组件

jsx 复制代码
import React from 'react';

const Square = ({ value, onClick }) => {
  return (
    <button 
      className="square" 
      onClick={onClick} 
      style={{
        width: '60px',
        height: '60px',
        fontSize: '24px',
        cursor: 'pointer'
      }}
    >
      {value}
    </button>
  );
};

export default Square;

Step 2: Board.js - 棋盘组件

jsx 复制代码
import React from 'react';
import Square from './Square';

const Board = ({ squares, onClick }) => {
  const renderSquare = (i) => {
    return <Square value={squares[i]} onClick={() => onClick(i)} />;
  };

  return (
    <div style={{
      display: 'flex',
      flexDirection: 'column',
      justifyContent: 'center',
      alignItems: 'center',
    }}>
      <div style={{ display: 'flex' }}>
        {renderSquare(0)}{renderSquare(1)}{renderSquare(2)}
      </div>
      <div style={{ display: 'flex' }}>
        {renderSquare(3)}{renderSquare(4)}{renderSquare(5)}
      </div>
      <div style={{ display: 'flex' }}>
        {renderSquare(6)}{renderSquare(7)}{renderSquare(8)}
      </div>
    </div>
  );
};

export default Board;

Step 3: App.js - 游戏逻辑和主组件

jsx 复制代码
import React, { useState } from 'react';
import Board from './Board';


const App = () => {
  const [squares, setSquares] = useState(Array(9).fill(null));
  const [isXNext, setIsXNext] = useState(true);

  const calculateWinner = (squares) => {
    const lines = [
      [0, 1, 2], [3, 4, 5], [6, 7, 8], // Rows
      [0, 3, 6], [1, 4, 7], [2, 5, 8], // Columns
      [0, 4, 8], [2, 4, 6]            // Diagonals
    ];
    for (let [a, b, c] of lines) {
      if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
        return squares[a];
      }
    }
    return null;
  };

  const winner = calculateWinner(squares);
  const handleClick = (i) => {
    if (squares[i] || winner) return; // Ignore if square is already filled or game is won
    const nextSquares = squares.slice();
    nextSquares[i] = isXNext ? 'X' : 'O';
    setSquares(nextSquares);
    setIsXNext(!isXNext);
  };

  const restartGame = () => {
    setSquares(Array(9).fill(null));
    setIsXNext(true);
  };

  const status = winner ? `Winner: ${winner}` : `Next Player: ${isXNext ? 'X' : 'O'}`;

  return (
    <div style={{ textAlign: 'center', marginTop: '50px' }}>
      <h1>Tic-Tac-Toe</h1>
      <Board squares={squares} onClick={handleClick} />
      <h3>{status}</h3>
      <button onClick={restartGame} style={{ padding: '10px 20px', marginTop: '20px' }}>
        Restart
      </button>
    </div>
  );
};

export default App;

Step 4: index.js - 渲染应用

jsx 复制代码
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

ReactDOM.render(<App />, document.getElementById('root'));

3. 启动应用:

bash 复制代码
npm start

打开浏览器,访问 http://localhost:3000 即可运行。如图所示:

希望这些内容对你有所帮助!如果有任何问题,欢迎随时提问。

相关推荐
We་ct16 小时前
LeetCode 5. 最长回文子串:DP + 中心扩展
前端·javascript·算法·leetcode·typescript
cn_mengbei1 天前
用React Native开发OpenHarmony应用:Reanimated共享元素过渡
javascript·react native·react.js
kyriewen1 天前
前端测试:别为了100%覆盖率而写测试,那是自欺欺人
前端·javascript·单元测试
Data_Journal1 天前
如何使用cURL更改User Agent
大数据·服务器·前端·javascript·数据库
掌心向暖RPA自动化1 天前
如何获取网页某个元素在屏幕可见部分的中心坐标影刀RPA懒加载坐标定位技巧
java·javascript·自动化·rpa·影刀rpa
竹林8181 天前
wagmi v2 多链钱包切换:一个 Uniswap 仿盘项目让我踩了三天坑
前端·javascript
你也向往长安城吗1 天前
最快的 JavaScript navmesh pathfinding3d 算法。
javascript
滕青山1 天前
在线PDF拆分工具核心JS实现
前端·javascript·vue.js
兔子零10241 天前
Ofox AI值得用吗?
前端·javascript·后端
We་ct1 天前
React 性能优化精讲
前端·javascript·react.js·性能优化·前端框架·html·浏览器