AI井字棋项目开发笔记

🚨 踩坑记录与解决方案

1. 路径导入问题

问题现象

typescript 复制代码
// 错误:找不到模块
import styles from './Board.module.css'; // TS2307错误

解决方案

方法一:创建类型声明文件

typescript 复制代码
// src/vite-env.d.ts
/// <reference types="vite/client" />

declare module '*.module.css' {
  const classes: { readonly [key: string]: string };
  export default classes;
}

declare module '*.css' {
  const classes: { readonly [key: string]: string };
  export default classes;
}

方法二:正确的相对路径导入

typescript 复制代码
// 组件导入其他组件
import { Square } from '../../ui/Square/Square'; // 明确文件路径
import { Button } from '../../ui/Button/Button';

// 避免使用index.ts快捷方式,直到配置正确

方法三:配置路径别名(推荐)

typescript 复制代码
// vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import path from 'path'

export default defineConfig({
  plugins: [react()],
  resolve: {
    alias: {
      '@': path.resolve(__dirname, './src'),
      '@components': path.resolve(__dirname, './src/components'),
      '@core': path.resolve(__dirname, './src/core')
    }
  }
})

// 然后在tsconfig.json中配置
{
  "compilerOptions": {
    "paths": {
      "@/*": ["./src/*"],
      "@components/*": ["./src/components/*"],
      "@core/*": ["./src/core/*"]
    }
  }
}

// 使用路径别名导入
import { Board } from '@components/game/Board/Board';
import { MinimaxAI } from '@core/algorithms/minimax';

🏗️ 项目架构详解

1. 现代前端项目架构概念

什么是项目架构?

就像盖房子需要蓝图一样,项目架构就是软件的"蓝图",它决定了:

  • 代码如何组织
  • 不同部分如何协作
  • 如何扩展和维护

我们的项目架构

复制代码
ai-tic-tac-toe/
├── src/
│   ├── components/     # 组件层 - 负责显示界面
│   ├── core/          # 核心层 - 负责业务逻辑
│   ├── hooks/         # 逻辑层 - 负责状态管理
│   └── styles/        # 样式层 - 负责外观

2. 模块化设计

什么是模块化?

把大系统拆成小模块,每个模块专注做一件事。

我们的模块划分

typescript 复制代码
// UI模块 - 只关心显示
export const Button: React.FC<ButtonProps> = ({ children, onClick }) => {
  return <button onClick={onClick}>{children}</button>;
};

// 业务模块 - 只关心游戏规则
export class MinimaxAI {
  getBestMove(board: BoardState): number {
    // AI算法实现
  }
}

// 状态模块 - 只关心数据管理
export const useGame = () => {
  const [board, setBoard] = useState(initialBoard);
  // 状态管理逻辑
};

模块化的好处

  • ✅ 代码更易理解
  • ✅ 便于团队协作
  • ✅ 容易测试和维护
  • ✅ 代码复用性强

3. 组件化设计

什么是组件化?

把界面拆分成独立的、可复用的部件。

我们的组件层次

复制代码
App (根组件)
└── GameLayout (布局组件)
    ├── GameStatus (状态显示)
    ├── Board (游戏棋盘)
    │   └── Square (单个格子) × 9
    └── GameControls (控制按钮)

组件通信方式

typescript 复制代码
// 1. 父传子 - Props
<Square value={squares[0]} onClick={() => handleClick(0)} />

// 2. 子传父 - 回调函数
const handleClick = (index: number) => {
  // 处理点击事件
};

// 3. 状态提升 - 共享状态
const [board, setBoard] = useState(initialBoard);

📚 TypeScript 工程化开发要点

1. 类型系统基础

为什么要用TypeScript?

  • 🛡️ 在代码运行前发现错误
  • 📝 代码即文档,类型就是注释
  • 🔧 更好的编辑器支持

基础类型示例

typescript 复制代码
// 原始类型
const name: string = "Alice";
const age: number = 25;
const isStudent: boolean = true;

// 数组类型
const numbers: number[] = [1, 2, 3];
const players: Array<'X' | 'O'> = ['X', 'O'];

// 对象类型
interface User {
  id: number;
  name: string;
  email?: string; // 可选属性
}

// 函数类型
const calculateScore: (board: BoardState) => number = (board) => {
  return 0;
};

2. React + TypeScript 集成

组件Props类型定义

typescript 复制代码
// 定义Props接口
interface SquareProps {
  value: 'X' | 'O' | null;      // 只能是这三个值
  onClick: () => void;          // 无参数无返回值的函数
  isWinning: boolean;           // 布尔值
  disabled: boolean;
}

// 使用组件
export const Square: React.FC<SquareProps> = (props) => {
  return (
    <button 
      onClick={props.onClick}
      disabled={props.disabled}
    >
      {props.value}
    </button>
  );
};

// 或者使用解构
export const Square: React.FC<SquareProps> = ({ 
  value, 
  onClick, 
  isWinning, 
  disabled 
}) => {
  // 组件实现
};

Hooks类型定义

typescript 复制代码
// useState - 自动推断类型
const [count, setCount] = useState(0); // count自动是number类型

// 明确指定类型
const [board, setBoard] = useState<BoardState>(initialBoard);

// useCallback - 记忆函数
const handleClick = useCallback((index: number): void => {
  // 这个函数会被记忆,依赖不变就不会重新创建
  makeMove(index);
}, [makeMove]); // 依赖列表

// useMemo - 记忆计算结果
const gameStatus = useMemo((): GameStatus => {
  // 昂贵的计算,结果会被缓存
  return calculateGameStatus(board);
}, [board]); // board变化时才重新计算

3. 配置文件详解

package.json - 项目身份证

json 复制代码
{
  "name": "ai-tic-tac-toe",
  "version": "1.0.0",
  "type": "module",          // 使用ES模块
  "scripts": {
    "dev": "vite",          // 开发命令
    "build": "tsc && vite build", // 构建命令
    "preview": "vite preview"    // 预览构建结果
  },
  "dependencies": {
    "react": "^18.2.0",     // 生产依赖
    "react-dom": "^18.2.0"
  },
  "devDependencies": {
    "@types/react": "^18.2.0", // 类型定义
    "typescript": "^5.0.2",   // 开发工具
    "vite": "^4.4.5"
  }
}

tsconfig.json - TypeScript配置

json 复制代码
{
  "compilerOptions": {
    "target": "ES2020",        // 编译目标版本
    "lib": ["ES2020", "DOM"],  // 使用的库文件
    "module": "ESNext",        // 模块系统
    "strict": true,            // 严格模式
    "jsx": "react-jsx",        // React JSX转换
    "esModuleInterop": true    // 模块互操作
  },
  "include": ["src"]          // 包含的文件
}

🔧 开发工作流

1. 开发环境搭建

步骤

  1. 安装Node.js (版本14+)
  2. 创建项目文件夹
  3. 初始化package.json: npm init -y
  4. 安装依赖: npm install react react-dom
  5. 安装开发依赖: npm install -D typescript @types/react vite
  6. 创建配置文件

2. 开发命令

bash 复制代码
# 启动开发服务器
npm run dev

# 代码检查
npm run lint

# 构建生产版本
npm run build

# 类型检查
npx tsc --noEmit

3. 调试技巧

浏览器开发者工具

  • F12打开开发者工具
  • Sources标签查看源代码
  • Console查看错误信息

React开发者工具

  • 浏览器扩展,专门调试React应用
  • 查看组件层次和状态

🎯 核心概念总结

1. ES Modules (ES模块)

什么是模块?

  • 一个文件就是一个模块
  • 使用import/export来导入导出

示例

typescript 复制代码
// math.ts - 导出模块
export const add = (a: number, b: number): number => a + b;
export const PI = 3.14159;

// app.ts - 导入模块
import { add, PI } from './math';
console.log(add(2, 3)); // 5

2. 组件生命周期

函数组件生命周期

typescript 复制代码
const MyComponent: React.FC = () => {
  // 1. 创建阶段 (每次渲染都执行)
  const [state, setState] = useState(initialState);
  
  // 2. 副作用阶段
  useEffect(() => {
    // 组件挂载后执行
    console.log('组件已挂载');
    
    return () => {
      // 组件卸载前执行
      console.log('组件即将卸载');
    };
  }, []); // 空依赖数组表示只执行一次
  
  // 3. 渲染阶段
  return <div>组件内容</div>;
};

3. 状态管理

状态提升

typescript 复制代码
// 子组件
const Child: React.FC<{ value: string; onChange: (value: string) => void }> = 
  ({ value, onChange }) => {
  return <input value={value} onChange={(e) => onChange(e.target.value)} />;
};

// 父组件
const Parent: React.FC = () => {
  const [value, setValue] = useState('');
  return <Child value={value} onChange={setValue} />;
};

📖 学习资源汇总

官方文档(必读)

  1. TypeScript

  2. React

  3. 构建工具

实践教程

  1. 项目实战

  2. 算法学习

工具资源

  1. 开发工具

  2. 代码质量

社区资源

  1. 学习社区

推荐学习路径

  1. 第一阶段:HTML/CSS/JavaScript基础
  2. 第二阶段:TypeScript语法和类型系统
  3. 第三阶段:React基础概念和Hooks
  4. 第四阶段:构建工具和项目配置
  5. 第五阶段:算法和数据结构
  6. 第六阶段:实战项目开发

记住:编程是实践技能,多写代码比只看文档更重要。从这个小项目开始,逐步构建知识体系。

相关推荐
~无忧花开~3 小时前
JavaScript实现PDF本地预览技巧
开发语言·前端·javascript
小时前端3 小时前
“能说说事件循环吗?”—— 我从候选人回答中看到的浏览器与Node.js核心差异
前端·面试·浏览器
Elias不吃糖3 小时前
LeetCode每日一练(209, 167)
数据结构·c++·算法·leetcode
IT_陈寒3 小时前
Vite 5.0实战:10个你可能不知道的性能优化技巧与插件生态深度解析
前端·人工智能·后端
SAP庖丁解码3 小时前
【SAP Web Dispatcher负载均衡】
运维·前端·负载均衡
天蓝色的鱼鱼4 小时前
Ant Design 6.0 正式发布:前端开发者的福音与革新
前端·react.js·ant design
HIT_Weston4 小时前
38、【Ubuntu】【远程开发】拉出内网 Web 服务:构建静态网页(一)
linux·前端·ubuntu
铁手飞鹰4 小时前
单链表(C语言,手撕)
数据结构·c++·算法·c·单链表
悦悦子a啊4 小时前
项目案例作业(选做):使用文件改造已有信息系统
java·开发语言·算法
小殊小殊4 小时前
【论文笔记】知识蒸馏的全面综述
人工智能·算法·机器学习