feat: 添加Makefile编译系统和BUILD文档

- 创建完整的Makefile支持make编译
- 支持编译控制台版本和GUI版本
- 添加清理、运行、帮助等目标
- 自动处理SDL3和网络库依赖
- 创建BUILD.md编译指南文档
- 完善GUI相关全局变量管理
- 丰富函数注释和文档
This commit is contained in:
2025-09-20 10:50:58 +08:00
parent 0e53b09d9b
commit a11ddeb8d1
9 changed files with 386 additions and 44 deletions
+1
View File
@@ -2,6 +2,7 @@
*.exe
*.out
*.app
*.o
# IDE配置文件
.idea/
+73
View File
@@ -0,0 +1,73 @@
# 五子棋游戏编译指南
本项目现在支持使用 `make` 命令进行编译,提供了更便捷的构建方式。
## 系统要求
- MinGW64 编译器
- SDL3 开发库(用于图形界面)
- Make 工具
## 编译命令
### 查看所有可用命令
```bash
make help
```
### 编译所有版本
```bash
make all
```
这将同时编译控制台版本和GUI版本。
### 只编译控制台版本
```bash
make console
```
生成 `gobang_console.exe`
### 只编译GUI版本
```bash
make gui
```
生成 `gobang_gui.exe`
### 清理编译文件
```bash
make clean
```
删除所有目标文件(.o)和可执行文件(.exe)
### 编译并运行
```bash
# 编译并运行控制台版本
make run-console
# 编译并运行GUI版本
make run-gui
```
## 生成的文件
- `gobang_console.exe` - 控制台版本,支持所有功能包括图形界面模式
- `gobang_gui.exe` - GUI版本,与控制台版本功能相同
## 注意事项
1. 两个版本都包含完整功能,包括图形界面支持
2. 需要确保SDL3库路径正确配置在Makefile中
3. 编译时会显示一些警告,这是正常的
4. 如果遇到编译错误,请检查MinGW64和SDL3的安装路径
## 传统编译方式
如果不使用Makefile,仍可以使用传统的gcc命令:
```bash
# 控制台版本
gcc -std=c17 -o gobang.exe *.c -lws2_32
# GUI版本
gcc -std=c17 -o gobang_gui.exe *.c -ID:\settings\SDL\SDL3-3.2.22\x86_64-w64-mingw32\include -LD:\settings\SDL\SDL3-3.2.22\x86_64-w64-mingw32\lib -lSDL3 -lws2_32
```
+80
View File
@@ -0,0 +1,80 @@
# 五子棋游戏 Makefile
# 支持编译控制台版本和GUI版本
# 编译器设置
CC = gcc
CFLAGS = -Wall -Wextra -std=c17 -O2
LDFLAGS = -lws2_32
# SDL3路径设置
SDL3_PATH = D:/settings/SDL/SDL3-3.2.22/x86_64-w64-mingw32
SDL3_INCLUDE = -I$(SDL3_PATH)/include
SDL3_LIBS = -L$(SDL3_PATH)/lib -lSDL3 -lmingw32
# 源文件
COMMON_SOURCES = main.c gobang.c ai.c config.c game_mode.c globals.c \
init_board.c network.c record.c ui.c gui.c type.h
GUI_SOURCES = $(COMMON_SOURCES)
CONSOLE_SOURCES = $(COMMON_SOURCES)
# 目标文件
COMMON_OBJECTS = $(patsubst %.c,%.o,$(filter %.c,$(COMMON_SOURCES)))
# 可执行文件
CONSOLE_TARGET = gobang_console.exe
GUI_TARGET = gobang_gui.exe
# 默认目标
all: $(CONSOLE_TARGET) $(GUI_TARGET)
# 控制台版本
$(CONSOLE_TARGET): $(COMMON_OBJECTS)
$(CC) $(CFLAGS) $(SDL3_INCLUDE) -o $@ $^ $(SDL3_LIBS) $(LDFLAGS)
# GUI版本
$(GUI_TARGET): $(COMMON_OBJECTS)
$(CC) $(CFLAGS) $(SDL3_INCLUDE) -o $@ $^ $(SDL3_LIBS) $(LDFLAGS)
# 通用目标文件编译规则(包含SDL3头文件路径,因为多个文件包含gui.h)
%.o: %.c
$(CC) $(CFLAGS) $(SDL3_INCLUDE) -c -o $@ $<
# 清理规则
clean:
del /Q *.o *.exe 2>nul || true
# 只编译控制台版本
console: $(CONSOLE_TARGET)
# 只编译GUI版本
gui: $(GUI_TARGET)
# 安装规则(可选)
install: all
@echo Installing executables...
copy $(CONSOLE_TARGET) C:\Program Files\Gobang\ 2>nul || echo Install directory not found
copy $(GUI_TARGET) C:\Program Files\Gobang\ 2>nul || echo Install directory not found
# 运行控制台版本
run-console: $(CONSOLE_TARGET)
.\$(CONSOLE_TARGET)
# 运行GUI版本
run-gui: $(GUI_TARGET)
.\$(GUI_TARGET)
# 帮助信息
help:
@echo Available targets:
@echo all - Build both console and GUI versions
@echo console - Build console version only
@echo gui - Build GUI version only
@echo clean - Remove all object files and executables
@echo run-console - Build and run console version
@echo run-gui - Build and run GUI version
@echo install - Install executables to system directory
@echo help - Show this help message
# 声明伪目标
.PHONY: all clean console gui install run-console run-gui help
+4 -12
View File
@@ -19,22 +19,10 @@
- 📱 **响应式界面** - 自适应窗口大小和分辨率
- 🚀 **性能优化** - 图形渲染和事件处理性能提升
### v7.0 (2025-07-20) - 代码架构重构更新
- 🏗️ **结构体定义集中化** - 所有数据结构统一管理在type.h中
- ⚙️ **配置参数统一管理** - 所有配置宏定义集中在config.h中
- 🔧 **代码模块化优化** - 消除重复定义,提高代码可维护性
- 📋 **菜单选项优化** - 退出选项调整为"0. 退出游戏"
- 🎯 **类型系统完善** - 独立的type.h文件管理所有数据类型
- 🌐 **网络配置重构** - 网络相关宏定义统一到config.h
- 📊 **全局变量管理** - 优化全局变量声明和定义结构
- 🔄 **头文件依赖优化** - 改进模块间依赖关系和包含结构
## 目录
- [C语言五子棋人机对战AI](#c语言五子棋人机对战ai)
- [📋 大版本更新](#-大版本更新)
- [v8.0 (2025-01-18) - GUI图形化界面更新](#v80-2025-01-18---gui图形化界面更新)
- [v7.0 (2025-07-20) - 代码架构重构更新](#v70-2025-07-20---代码架构重构更新)
- [目录](#目录)
- [项目简介](#项目简介)
- [功能特性](#功能特性)
@@ -45,7 +33,11 @@
- [🔧 技术特性](#-技术特性)
- [快速开始](#快速开始)
- [编译项目](#编译项目)
- [控制台版本编译](#控制台版本编译)
- [GUI版本编译(需要SDL3](#gui版本编译需要sdl3)
- [运行游戏](#运行游戏)
- [控制台版本](#控制台版本)
- [GUI版本](#gui版本)
- [游戏玩法](#游戏玩法)
- [🚀 快速开始](#-快速开始)
- [🎯 对局操作](#-对局操作)
+17 -1
View File
@@ -116,7 +116,23 @@
#define TIME_WEIGHT_FACTOR 0.5 // 时间权重因子
#define WIN_BONUS 2000 // 胜利奖励分数
// 文件路径参数
//---------- GUI界面参数 ----------//
// 窗口和棋盘配置
#define WINDOW_WIDTH 800
#define WINDOW_HEIGHT 600
#define BOARD_OFFSET_X 50
#define BOARD_OFFSET_Y 50
#define CELL_SIZE 30
#define STONE_RADIUS 12
// 颜色定义
#define GUI_COLOR_BACKGROUND {240, 217, 181, 255}
#define GUI_COLOR_BOARD_LINE {0, 0, 0, 255}
#define GUI_COLOR_BLACK_STONE {0, 0, 0, 255}
#define GUI_COLOR_WHITE_STONE {255, 255, 255, 255}
#define GUI_COLOR_STONE_BORDER {100, 100, 100, 255}
//---------- 文件路径参数 ----------//
#define RECORDS_DIR "records" // 记录文件目录
#define CONFIG_FILE "gobang_config.ini" // 配置文件路径
#define MAX_PATH_LENGTH 256 // 最大路径长度
+9
View File
@@ -7,6 +7,7 @@
#include "globals.h"
#include "config.h"
#include <SDL3/SDL.h>
// ==================== 游戏核心变量定义 ====================
int BOARD_SIZE = DEFAULT_BOARD_SIZE; // 实际使用的棋盘尺寸
@@ -28,6 +29,14 @@ double defense_coefficient = DEFAULT_DEFENSE_COEFFICIENT; // 防守系数
// ==================== 网络相关变量定义 ====================
NetworkGameState network_state = {0}; // 网络游戏状态
// ==================== GUI相关变量定义 ====================
SDL_Window* window = NULL; // SDL窗口指针
SDL_Renderer* renderer = NULL; // SDL渲染器指针
int gui_running = 1; // GUI运行状态标志
int current_player_gui = PLAYER; // GUI当前玩家
int game_over = 0; // 游戏结束标志
char status_message[256] = "五子棋游戏 - 黑子先行"; // 状态消息
// ==================== 记录相关变量定义 ====================
int player1_final_score = 0; // 玩家1最终得分
int player2_final_score = 0; // 玩家2最终得分
+9
View File
@@ -11,6 +11,7 @@
#include "gobang.h"
#include "network.h"
#include <stdbool.h>
#include <SDL3/SDL.h>
// ==================== 游戏核心变量 ====================
extern int BOARD_SIZE; // 当前实际使用的棋盘尺寸
@@ -32,6 +33,14 @@ extern double defense_coefficient; // 防守系数
// ==================== 网络相关变量 ====================
extern NetworkGameState network_state; // 网络游戏状态
// ==================== GUI相关变量 ====================
extern SDL_Window* window; // SDL窗口指针
extern SDL_Renderer* renderer; // SDL渲染器指针
extern int gui_running; // GUI运行状态标志
extern int current_player_gui; // GUI当前玩家
extern int game_over; // 游戏结束标志
extern char status_message[256]; // 状态消息
// ==================== 记录相关变量 ====================
extern int player1_final_score; // 玩家1最终得分
extern int player2_final_score; // 玩家2最终得分
+66 -8
View File
@@ -15,17 +15,17 @@
#include <stdlib.h>
#include <math.h>
// 全局变量
SDL_Window* window = NULL;
SDL_Renderer* renderer = NULL;
int gui_running = 1;
int current_player_gui = PLAYER;
int game_over = 0;
char status_message[256] = "五子棋游戏 - 黑子先行";
/**
* @brief 初始化GUI
* @details 初始化SDL3图形库和游戏界面组件:
* - 初始化SDL视频子系统
* - 创建游戏窗口(可调整大小)
* - 创建SDL渲染器
* - 初始化游戏状态和棋盘数据
* @return 成功返回0,失败返回-1
* @note 窗口标题为"五子棋游戏 - SDL3版本"
* 窗口尺寸由WINDOW_WIDTH和WINDOW_HEIGHT定义
* 失败时会自动清理已创建的资源
*/
int init_gui() {
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
@@ -78,6 +78,13 @@ int init_gui() {
/**
* @brief 清理GUI资源
* @details 按顺序释放所有SDL相关资源:
* - 销毁SDL渲染器
* - 销毁SDL窗口
* - 退出SDL子系统
* @note 函数会检查资源是否存在再进行释放
* 释放后将指针设置为NULL防止重复释放
* 程序退出时必须调用此函数避免内存泄漏
*/
void cleanup_gui() {
if (renderer) {
@@ -94,6 +101,15 @@ void cleanup_gui() {
/**
* @brief 渲染游戏画面
* @details 完整的游戏画面渲染流程:
* - 清空屏幕并设置背景色
* - 绘制棋盘网格和标记点
* - 绘制所有棋子
* - 绘制UI界面元素
* - 将渲染结果显示到屏幕
* @note 使用双缓冲技术,通过SDL_RenderPresent显示最终结果
* 背景色由GUI_COLOR_BACKGROUND定义
* 每帧都会完全重绘整个画面
*/
void render_game() {
// 清空屏幕 - 设置背景色
@@ -116,7 +132,14 @@ void render_game() {
/**
* @brief 处理事件
* @details 处理所有SDL事件并执行相应操作:
* - SDL_EVENT_QUIT:用户关闭窗口
* - SDL_EVENT_KEY_DOWN:键盘按键(ESC退出)
* - SDL_EVENT_MOUSE_BUTTON_DOWN:鼠标点击落子
* @return 继续运行返回1,退出返回0
* @note 鼠标左键点击会转换为棋盘坐标并尝试落子
* 落子后会检查胜负并切换玩家
* 游戏结束后不再响应落子操作
*/
int handle_events() {
SDL_Event event;
@@ -172,6 +195,13 @@ int handle_events() {
/**
* @brief 绘制棋盘
* @details 绘制15x15的五子棋棋盘,包括:
* - 横竖交叉的网格线
* - 天元点(棋盘中心的标记点)
* - 四个星位(棋盘上的定位点)
* @note 使用SDL3渲染器绘制线条和填充矩形
* 棋盘线条颜色由GUI_COLOR_BOARD_LINE定义
* 天元点和星位用黑色小矩形标记
*/
void draw_board() {
SDL_Color line_color = GUI_COLOR_BOARD_LINE;
@@ -222,6 +252,13 @@ void draw_board() {
/**
* @brief 绘制棋子
* @details 遍历整个棋盘数组,绘制所有已落下的棋子:
* - 黑子:使用GUI_COLOR_BLACK_STONE颜色
* - 白子:使用GUI_COLOR_WHITE_STONE颜色
* - 每个棋子都有边框:使用GUI_COLOR_STONE_BORDER颜色
* @note 棋子绘制为圆形,半径由STONE_RADIUS定义
* 通过draw_circle函数实现圆形绘制
* 棋子位置根据棋盘坐标和CELL_SIZE计算屏幕坐标
*/
void draw_stones() {
for (int i = 0; i < BOARD_SIZE; i++) {
@@ -256,6 +293,13 @@ void draw_stones() {
* @param center_y 圆心Y坐标
* @param radius 半径
* @param color 颜色
* @details 使用像素级绘制实现圆形:
* - 遍历圆形外接矩形内的所有像素点
* - 计算每个像素到圆心的距离
* - 距离小于等于半径的像素点进行着色
* @note 采用暴力算法,性能较低但实现简单
* 适用于绘制棋子等小尺寸圆形
* SDL3没有内置圆形绘制函数,需要自实现
*/
void draw_circle(int center_x, int center_y, int radius, SDL_Color color) {
SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, color.a);
@@ -311,6 +355,13 @@ void draw_ui_elements() {
* @param board_x 输出棋盘X坐标
* @param board_y 输出棋盘Y坐标
* @return 转换成功返回1,失败返回0
* @details 坐标转换算法:
* - 减去棋盘偏移量得到相对坐标
* - 加上半个格子尺寸实现就近取整
* - 除以格子尺寸得到棋盘坐标
* - 检查坐标是否在有效范围内
* @note 使用就近取整算法,点击格子中心附近都会定位到该格子
* 坐标范围检查确保不会越界访问棋盘数组
*/
int screen_to_board(int screen_x, int screen_y, int* board_x, int* board_y) {
int rel_x = screen_x - BOARD_OFFSET_X;
@@ -326,6 +377,13 @@ int screen_to_board(int screen_x, int screen_y, int* board_x, int* board_y) {
/**
* @brief 显示消息
* @param message 要显示的消息
* @details 消息显示功能:
* - 将消息复制到全局状态消息缓冲区
* - 同时在控制台输出消息内容
* - 确保字符串安全复制,防止缓冲区溢出
* @note 消息会存储在status_message全局变量中
* 字符串长度限制为缓冲区大小减1
* 消息可用于游戏状态提示和错误信息显示
*/
void show_message(const char* message) {
strncpy(status_message, message, sizeof(status_message) - 1);
+127 -23
View File
@@ -11,40 +11,144 @@
#include <SDL3/SDL.h>
#include "gobang.h"
// 窗口和棋盘配置
#define WINDOW_WIDTH 800
#define WINDOW_HEIGHT 600
#define BOARD_OFFSET_X 50
#define BOARD_OFFSET_Y 50
#define CELL_SIZE 30
#define STONE_RADIUS 12
// 颜色定义
#define GUI_COLOR_BACKGROUND {240, 217, 181, 255}
#define GUI_COLOR_BOARD_LINE {0, 0, 0, 255}
#define GUI_COLOR_BLACK_STONE {0, 0, 0, 255}
#define GUI_COLOR_WHITE_STONE {255, 255, 255, 255}
#define GUI_COLOR_STONE_BORDER {100, 100, 100, 255}
#include "config.h"
#include "globals.h"
// GUI函数声明
/**
* @brief 初始化GUI
* @details 初始化SDL3图形库和游戏界面组件:
* - 初始化SDL视频子系统
* - 创建游戏窗口(可调整大小)
* - 创建SDL渲染器
* - 初始化游戏状态和棋盘数据
* @return 成功返回0,失败返回-1
* @note 窗口标题为"五子棋游戏 - SDL3版本"
* 窗口尺寸由WINDOW_WIDTH和WINDOW_HEIGHT定义
* 失败时会自动清理已创建的资源
*/
int init_gui();
/**
* @brief 清理GUI资源
* @details 按顺序释放所有SDL相关资源:
* - 销毁SDL渲染器
* - 销毁SDL窗口
* - 退出SDL子系统
* @note 函数会检查资源是否存在再进行释放
* 释放后将指针设置为NULL防止重复释放
* 程序退出时必须调用此函数避免内存泄漏
*/
void cleanup_gui();
/**
* @brief 渲染游戏画面
* @details 完整的游戏画面渲染流程:
* - 清空屏幕并设置背景色
* - 绘制棋盘网格和标记点
* - 绘制所有棋子
* - 绘制UI界面元素
* - 将渲染结果显示到屏幕
* @note 使用双缓冲技术,通过SDL_RenderPresent显示最终结果
* 背景色由GUI_COLOR_BACKGROUND定义
* 每帧都会完全重绘整个画面
*/
void render_game();
/**
* @brief 处理事件
* @details 处理所有SDL事件并执行相应操作:
* - SDL_EVENT_QUIT:用户关闭窗口
* - SDL_EVENT_KEY_DOWN:键盘按键(ESC退出)
* - SDL_EVENT_MOUSE_BUTTON_DOWN:鼠标点击落子
* @return 继续运行返回1,退出返回0
* @note 鼠标左键点击会转换为棋盘坐标并尝试落子
* 落子后会检查胜负并切换玩家
* 游戏结束后不再响应落子操作
*/
int handle_events();
/**
* @brief 绘制棋盘
* @details 绘制15x15的五子棋棋盘,包括:
* - 横竖交叉的网格线
* - 天元点(棋盘中心的标记点)
* - 四个星位(棋盘上的定位点)
* @note 使用SDL3渲染器绘制线条和填充矩形
* 棋盘线条颜色由GUI_COLOR_BOARD_LINE定义
* 天元点和星位用黑色小矩形标记
*/
void draw_board();
/**
* @brief 绘制棋子
* @details 遍历整个棋盘数组,绘制所有已落下的棋子:
* - 黑子:使用GUI_COLOR_BLACK_STONE颜色
* - 白子:使用GUI_COLOR_WHITE_STONE颜色
* - 每个棋子都有边框:使用GUI_COLOR_STONE_BORDER颜色
* @note 棋子绘制为圆形,半径由STONE_RADIUS定义
* 通过draw_circle函数实现圆形绘制
* 棋子位置根据棋盘坐标和CELL_SIZE计算屏幕坐标
*/
void draw_stones();
/**
* @brief 绘制UI元素
* @details 绘制游戏界面的用户交互元素:
* - 状态信息区域背景和边框
* - 当前玩家指示器(黑子或白子圆形)
* - 游戏状态显示区域
* @note 暂时使用简单图形代替文字显示
* 需要额外字体库支持文字渲染
* 指示器位置在棋盘右侧固定区域
*/
void draw_ui_elements();
/**
* @brief 绘制圆形
* @param center_x 圆心X坐标
* @param center_y 圆心Y坐标
* @param radius 半径
* @param color 颜色
* @details 使用像素级绘制实现圆形:
* - 遍历圆形外接矩形内的所有像素点
* - 计算每个像素到圆心的距离
* - 距离小于等于半径的像素点进行着色
* @note 采用暴力算法,性能较低但实现简单
* 适用于绘制棋子等小尺寸圆形
* SDL3没有内置圆形绘制函数,需要自实现
*/
void draw_circle(int center_x, int center_y, int radius, SDL_Color color);
/**
* @brief 屏幕坐标转棋盘坐标
* @param screen_x 屏幕X坐标
* @param screen_y 屏幕Y坐标
* @param board_x 输出棋盘X坐标
* @param board_y 输出棋盘Y坐标
* @return 转换成功返回1,失败返回0
* @details 坐标转换算法:
* - 减去棋盘偏移量得到相对坐标
* - 加上半个格子尺寸实现就近取整
* - 除以格子尺寸得到棋盘坐标
* - 检查坐标是否在有效范围内
* @note 使用就近取整算法,点击格子中心附近都会定位到该格子
* 坐标范围检查确保不会越界访问棋盘数组
*/
int screen_to_board(int screen_x, int screen_y, int *board_x, int *board_y);
/**
* @brief 显示消息
* @param message 要显示的消息
* @details 消息显示功能:
* - 将消息复制到全局状态消息缓冲区
* - 同时在控制台输出消息内容
* - 确保字符串安全复制,防止缓冲区溢出
* @note 消息会存储在status_message全局变量中
* 字符串长度限制为缓冲区大小减1
* 消息可用于游戏状态提示和错误信息显示
*/
void show_message(const char *message);
// 全局GUI变量
extern SDL_Window *window;
extern SDL_Renderer *renderer;
extern int gui_running;
extern int current_player_gui;
extern int game_over;
extern char status_message[256];
#endif // GUI_H