工程结构

对局规则 定下了玩家能看到的输入、输出与对局结果。井字棋工程把这些外部表现对应到目录和文件,先看目录分工,再看每类内容该放进哪个文件。

目录分工

工程根下的目录各放这些内容:

  • 动态库:tictactoe/ 保存棋盘、对局与电脑落子,编译成动态库供程序调用。
  • 程序入口:apps/ 当前只编译 main.cpp,由它最小调用动态库;终端程序的 cli.h、cli.cpp 保留在同一目录,但暂不参与构建。
  • 测试:tests/ 保存棋盘测试;tictactoe_test 已接入构建,由 CTest 运行 15 条用例。
  • CMake 复用:cmake/ 当前只保留 CompileSettings.cmake,用它声明 C++ 标准、选择警告等级。
  • 回放与网页脚本:python/ 提供对局回放与本地网页,通过 JSON 快照读取对局,不参与 C++ 构建。
  • 构建产物:build/ 由配置和编译生成,存放可执行文件、动态库文件与测试程序。
注意构建目录不含源码

构建目录 build/ 里是生成物,没有源码。整个目录可以删掉,也可以换一个路径;下一次配置和编译会按源码重新生成。

文件位置

工程自己的配置、源码、脚本与构建产物这样分布;行尾注释说明每一项是什么,目录用 #/,文件用 #:

games/tictactoe/
├── CMakeLists.txt                         # 整份工程的构建规则
├── apps/                                 #/ 程序入口
│   ├── src/main.cpp                       # 最小动态库调用
│   ├── include/cli.h                      # 终端程序接口,暂未接入
│   └── src/cli.cpp                        # 终端程序实现,暂未接入
├── build/                                #/ 构建产物
├── cmake/                                #/ 构建函数
│   └── CompileSettings.cmake              # 编译设置
├── python/                               #/ 回放与网页
├── running-build.sh                       # 编译与测试入口
├── tests/                                #/ 棋盘测试
│   ├── CMakeLists.txt                     # 测试构建规则
│   └── testing-board.cpp                  # 15 条棋盘用例
└── tictactoe/                            #/ 动态库
    ├── include/board.h                    # 棋盘尺寸与坐标
    ├── include/game.h                     # 对局规则
    ├── include/ai.h                       # 电脑落子
    ├── src/board.cpp                      # 棋盘实现
    ├── src/game.cpp                       # 对局实现
    └── src/ai.cpp                         # 电脑落子实现

头文件写接口,源文件写实现;tictactoe/ 编译成动态库。apps/ 的 app 链接它,tests/ 的 tictactoe_test 链接同一份库并由 CTest 运行。build/bin/ 放可执行文件,build/lib/ 放动态库文件,两处都由编译生成。

常见错误

打印逻辑混进动态库

动态库里出现 std::cout 后,测试或换界面都得连终端一起处理。

  • 出错的原因:显示属于调用方,库一旦直接打印,就把终端绑进了可复用代码。
  • 正确的做法:动态库返回数据,apps/ 的终端层决定怎样显示。

构建产物当作源码

在 build/ 里新建头文件或改 CMakeLists.txt,换一个构建目录就丢失。

  • 出错的原因:build/ 由编译生成,清理或重新编译会覆盖其中的手工改动。
  • 正确的做法:源码和脚本放在 apps/、tictactoe/、tests/、cmake/、python/ 这五个目录里。根目录放 CMakeLists.txt、running-build.sh 和三个 clang 配置文件。

自测问题

  1. 要查找棋盘格子的保存位置,先看 apps/、tests/ 还是 tictactoe/ 目录?

    查看答案

    先看动态库目录 tictactoe/。棋盘格子的定义在其中的 include/board.h,实现放在 src/board.cpp。

  2. 打印棋盘由终端程序实现,还是由动态库实现?

    查看答案

    由终端程序实现。打印棋盘和读入坐标属于文本交流,放在 apps/。动态库保存棋盘、对局与电脑落子,供终端程序调用。

  3. 构建完成后,可执行文件和动态库文件分别放在 build/ 的 bin/ 还是 lib/?

    查看答案

    可执行文件在 build/bin/,动态库文件在 build/lib/。

本章回顾

你已经能在工程目录里找到动态库、程序入口与测试目录,也能找到保留未接入的终端程序。你还能说出 build/ 为什么可以删掉后重新生成。下一章是程序结构,看这四块怎样连成一份程序。