From f897536a457d53f3646bb47bde9a514c973e4d40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E8=88=AA=E5=AE=87?= <3364451258@qq.com> Date: Sat, 2 May 2026 12:24:27 +0800 Subject: [PATCH] =?UTF-8?q?refactor(config):=20=E6=9B=B4=E6=96=B0=E6=97=B6?= =?UTF-8?q?=E9=97=B4=E9=99=90=E5=88=B6=E4=B8=BA30=E5=88=86=E9=92=9F?= =?UTF-8?q?=E5=B9=B6=E8=B0=83=E6=95=B4=E9=85=8D=E7=BD=AE=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E5=AD=98=E5=82=A8=E6=A0=BC=E5=BC=8F=20refactor(globals):=20?= =?UTF-8?q?=E7=A7=BB=E9=99=A4=E4=B8=8D=E5=BF=85=E8=A6=81=E7=9A=84GUI?= =?UTF-8?q?=E8=BF=90=E8=A1=8C=E7=8A=B6=E6=80=81=E6=A0=87=E5=BF=97=20refact?= =?UTF-8?q?or(gui):=20=E6=9B=B4=E6=96=B0=E6=B3=A8=E9=87=8A=E4=BB=A5?= =?UTF-8?q?=E5=8F=8D=E6=98=A0=E4=BD=BF=E7=94=A8IUP=E5=BA=93=20refactor(ai)?= =?UTF-8?q?:=20=E4=BF=AE=E6=94=B9=E5=A8=81=E8=83=81=E6=A3=80=E6=B5=8B?= =?UTF-8?q?=E9=80=BB=E8=BE=91=E4=BB=A5=E6=8F=90=E5=8D=87=E5=A8=81=E8=83=81?= =?UTF-8?q?=E7=AD=89=E7=BA=A7=20refactor(config):=20=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E5=8A=A0=E8=BD=BD=E5=92=8C=E4=BF=9D=E5=AD=98=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E7=9A=84=E6=97=B6=E9=97=B4=E9=99=90=E5=88=B6=E9=80=BB=E8=BE=91?= =?UTF-8?q?=20refactor(network):=20=E6=9B=B4=E6=96=B0=E9=BB=98=E8=AE=A4?= =?UTF-8?q?=E7=BD=91=E7=BB=9C=E7=AB=AF=E5=8F=A3=E5=B8=B8=E9=87=8F=20refact?= =?UTF-8?q?or(record):=20=E7=A7=BB=E9=99=A4=E5=86=97=E4=BD=99=E6=B3=A8?= =?UTF-8?q?=E9=87=8A=E5=B9=B6=E5=A2=9E=E5=BC=BA=E5=A4=8D=E7=9B=98=E6=AD=A5?= =?UTF-8?q?=E9=AA=A4=E7=9A=84=E5=90=88=E6=B3=95=E6=80=A7=E6=A3=80=E6=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/config.h | 6 ++---- include/globals.h | 2 -- include/gui.h | 42 +++--------------------------------------- include/gui_internal.h | 1 - src/ai.c | 5 +++-- src/config.c | 8 ++++++-- src/globals.c | 1 - src/gui_core.c | 3 --- src/gui_menu.c | 6 +++--- src/main.c | 1 - src/network.c | 2 +- src/record.c | 35 +++++++++++------------------------ 12 files changed, 29 insertions(+), 83 deletions(-) diff --git a/include/config.h b/include/config.h index ae34b0a..445386f 100644 --- a/include/config.h +++ b/include/config.h @@ -34,7 +34,7 @@ //---------- 游戏设置默认值 ----------// #define DEFAULT_USE_FORBIDDEN_MOVES false // 默认不启用禁手规则 #define DEFAULT_USE_TIMER 0 // 默认不启用计时器 -#define DEFAULT_TIME_LIMIT 30 // 默认时间限制为30秒(内部存储) +#define DEFAULT_TIME_LIMIT 1800 // 默认时间限制为30分钟(内部以秒存储: 30*60) //---------- AI参数 ----------// #define DEFAULT_AI_DEPTH 5 // 默认AI搜索深度 @@ -48,8 +48,6 @@ #define NETWORK_BUFFER_SIZE 1024 // 网络缓冲区大小 // 网络配置 -#define DEFAULT_PORT 8888 // 默认端口(与DEFAULT_NETWORK_PORT保持一致) -#define BUFFER_SIZE 1024 // 缓冲区大小(与NETWORK_BUFFER_SIZE保持一致) #define MAX_IP_LENGTH 16 // 最大IP地址长度 // 网络消息类型 @@ -65,7 +63,7 @@ //---------- 评分参数 ----------// // 棋型评分 - 用于calculate_step_score函数 -#define SCORE_FIVE 0 // 五连 +#define SCORE_FIVE 5000 // 五连 #define SCORE_LIVE_FOUR 2000 // 活四 #define SCORE_RUSH_FOUR 1000 // 冲四 #define SCORE_DEAD_FOUR 300 // 死四 diff --git a/include/globals.h b/include/globals.h index 4a389ed..f02f2f9 100644 --- a/include/globals.h +++ b/include/globals.h @@ -33,8 +33,6 @@ extern int ai_difficulty; // AI难度 (1-5) extern NetworkGameState network_state; // 网络游戏状态 // ==================== GUI相关变量 ==================== -// Raylib 不需要暴露窗口和渲染器指针 -extern int gui_running; // GUI运行状态标志 extern int current_player_gui; // GUI当前玩家 extern int game_over; // 游戏结束标志 extern char status_message[256]; // 状态消息 diff --git a/include/gui.h b/include/gui.h index cc0ff47..dd503c9 100644 --- a/include/gui.h +++ b/include/gui.h @@ -1,9 +1,8 @@ /** * @file gui.h * @brief 图形化用户界面头文件 - * @note 使用Raylib库实现五子棋的图形化界面 + * @note 使用IUP库实现五子棋的图形化界面 * @author 刘航宇 - * @date 2025-01-15 */ #ifndef GUI_H @@ -17,45 +16,16 @@ /** * @brief 初始化GUI - * @details 初始化Raylib图形库和游戏界面组件 + * @details 初始化IUP图形库和游戏界面组件 * @return 成功返回0,失败返回-1 */ int init_gui(); /** * @brief 清理GUI资源 - * @details 关闭窗口 */ void cleanup_gui(); -/** - * @brief 渲染游戏画面 - * @details 完整的游戏画面渲染流程 - */ -void render_game(); - -/** - * @brief 处理事件 - * @details 处理所有Raylib事件并执行相应操作 - * @return 继续运行返回1,退出返回0 - */ -int handle_events(); - -/** - * @brief 绘制棋盘 - */ -void draw_board(); - -/** - * @brief 绘制棋子 - */ -void draw_stones(); - -/** - * @brief 绘制UI元素 - */ -void draw_ui_elements(); - /** * @brief 屏幕坐标转棋盘坐标 */ @@ -81,16 +51,10 @@ void start_pve_game_gui(); */ void start_replay_gui(); -/** - * @brief 启动图形化界面模式 - * @note 替代原来的 main 函数中的 GUI 分支逻辑 - */ -int init_gui(); // Already declared - /** * @brief 运行图形化界面模式 * @details 主循环处理事件、渲染画面和更新状态 */ void run_gui_mode(); -#endif // GUI_H \ No newline at end of file +#endif // GUI_H diff --git a/include/gui_internal.h b/include/gui_internal.h index 7694205..962dd30 100644 --- a/include/gui_internal.h +++ b/include/gui_internal.h @@ -8,7 +8,6 @@ extern Ihandle *dlg; extern Ihandle *board_canvas; extern Ihandle *lbl_player; extern Ihandle *lbl_status; -extern int gui_loop_running; extern int gui_game_mode; // 0: PvP, 1: PvE, 2: Replay extern int replay_total_steps; // 复盘总步数 diff --git a/src/ai.c b/src/ai.c index 999b9be..cf1811b 100644 --- a/src/ai.c +++ b/src/ai.c @@ -532,8 +532,9 @@ ThreatLevel detect_threat(int x, int y, int player) // 恢复棋盘 board[x][y] = EMPTY; - // 如果有多个威胁,提升威胁等级 - if (threat_count >= 2 && max_threat >= THREAT_THREE) + // 如果有多个活三威胁,升级为双威胁(如双三、四三等组合) + // 注意:不能把已经是活四的威胁降级为双威胁 + if (threat_count >= 2 && max_threat == THREAT_THREE) { max_threat = THREAT_DOUBLE; } diff --git a/src/config.c b/src/config.c index 2811f43..85d3275 100644 --- a/src/config.c +++ b/src/config.c @@ -48,7 +48,11 @@ void load_game_config() } else if (strncmp(line, "TIME_LIMIT=", 11) == 0) { - time_limit = atoi(line + 11); + int minutes = atoi(line + 11); + if (minutes > 0) + { + time_limit = minutes * 60; // 配置文件存分钟,内部转为秒 + } } else if (strncmp(line, "NETWORK_PORT=", 13) == 0) { @@ -101,7 +105,7 @@ void save_game_config() fprintf(file, "\n# 计时器 (0=关闭, 1=开启)\n"); fprintf(file, "USE_TIMER=%d\n", use_timer); fprintf(file, "\n# 时间限制 (分钟)\n"); - fprintf(file, "TIME_LIMIT=%d\n", time_limit); + fprintf(file, "TIME_LIMIT=%d\n", time_limit / 60); // 内部存秒,配置文件存分钟 fprintf(file, "\n# 网络端口 (范围: %d-%d)\n", MIN_NETWORK_PORT, MAX_NETWORK_PORT); fprintf(file, "NETWORK_PORT=%d\n", network_port); fprintf(file, "\n# 网络超时时间 (毫秒)\n"); diff --git a/src/globals.c b/src/globals.c index b4d495f..56075f5 100644 --- a/src/globals.c +++ b/src/globals.c @@ -30,7 +30,6 @@ int ai_difficulty = 3; // AI难度 (1-5) NetworkGameState network_state = {0}; // 网络游戏状态 // ==================== GUI相关变量定义 ==================== -int gui_running = 1; // GUI运行状态标志 int current_player_gui = PLAYER; // GUI当前玩家 int game_over = 0; // 游戏结束标志 char status_message[256] = "五子棋游戏 - 黑子先行"; // 状态消息 diff --git a/src/gui_core.c b/src/gui_core.c index 17ddc58..d4d2da8 100644 --- a/src/gui_core.c +++ b/src/gui_core.c @@ -11,7 +11,6 @@ Ihandle *dlg = NULL; Ihandle *board_canvas = NULL; Ihandle *lbl_player = NULL; Ihandle *lbl_status = NULL; -int gui_loop_running = 0; int gui_game_mode = 0; // 0: PvP, 1: PvE, 2: Replay, 3: Network int replay_total_steps = 0; // 复盘总步数 @@ -32,8 +31,6 @@ int init_gui() create_main_menu(); show_main_menu(); - gui_loop_running = 1; - printf("图形化界面初始化成功!(IUP)\n"); return 0; } diff --git a/src/gui_menu.c b/src/gui_menu.c index 71e42aa..4f65077 100644 --- a/src/gui_menu.c +++ b/src/gui_menu.c @@ -37,7 +37,7 @@ static int btn_network_host_cb(Ihandle *ih) Ihandle *dlg = IupGetDialog(ih); Ihandle *txt_port = IupGetDialogChild(dlg, "NET_PORT"); int port = IupGetInt(txt_port, "VALUE"); - if (port <= 0 || port > 65535) port = DEFAULT_PORT; + if (port <= 0 || port > 65535) port = DEFAULT_NETWORK_PORT; if (create_server(port)) { @@ -61,7 +61,7 @@ static int btn_network_join_cb(Ihandle *ih) char *ip = IupGetAttribute(txt_ip, "VALUE"); int port = IupGetInt(txt_port, "VALUE"); - if (port <= 0 || port > 65535) port = DEFAULT_PORT; + if (port <= 0 || port > 65535) port = DEFAULT_NETWORK_PORT; if (connect_to_server(ip, port)) { @@ -97,7 +97,7 @@ static int btn_network_cb(Ihandle *ih) Ihandle *txt_port = IupText(NULL); IupSetAttribute(txt_port, "NAME", "NET_PORT"); char port_str[16]; - sprintf(port_str, "%d", DEFAULT_PORT); + sprintf(port_str, "%d", DEFAULT_NETWORK_PORT); IupSetAttribute(txt_port, "VALUE", port_str); IupSetAttribute(txt_port, "SIZE", "50x"); diff --git a/src/main.c b/src/main.c index 221211d..4a4f083 100644 --- a/src/main.c +++ b/src/main.c @@ -25,7 +25,6 @@ int main(int argc, char *argv[]) { // 设置控制台编码为UTF-8 #ifdef _WIN32 - system("chcp 65001 > nul"); // 设置控制台编码为UTF-8 SetConsoleOutputCP(65001); // 设置控制台输出编码 SetConsoleCP(65001); // 设置控制台输入编码 _mkdir("records"); diff --git a/src/network.c b/src/network.c index 7e2e25c..76fefa4 100644 --- a/src/network.c +++ b/src/network.c @@ -26,7 +26,7 @@ bool init_network() } memset(&network_state, 0, sizeof(NetworkGameState)); - network_state.port = DEFAULT_PORT; + network_state.port = DEFAULT_NETWORK_PORT; return true; } diff --git a/src/record.c b/src/record.c index 24787e2..9063e7b 100644 --- a/src/record.c +++ b/src/record.c @@ -23,29 +23,6 @@ #include #endif -/** - * @brief 复盘游戏全过程并展示评分 - * @note 实现流程: - * 1. 初始化临时复盘棋盘 - * 2. 按步数顺序逐步重现每个落子 - * 3. 每步显示: - * - 当前步数/总步数 - * - 落子方(玩家/AI) - * - 落子位置(1-based坐标) - * - 当前棋盘状态 - * 4. 通过用户按Enter键控制步骤前进 - * 5. 复盘结束后自动进入评分环节: - * - 评估双方表现 - * - 显示得分 - * - 评选MVP - * @note 技术细节: - * - 使用独立临时棋盘避免影响主游戏状态 - * - 坐标显示转换为1-based方便用户理解 - * - 包含输入缓冲区清理防止意外输入 - * - 评分环节调用calculate_final_score()函数 - */ -void calculate_game_scores(); - /** * @brief 计算游戏评分 */ @@ -99,7 +76,7 @@ void calculate_game_scores() void display_game_scores(int game_mode) { printf("\n===== 对局评分 =====\n"); - double sum_score = (long double)player1_final_score + (long double)player2_final_score; + double sum_score = (double)player1_final_score + (double)player2_final_score; if (sum_score > 0) { @@ -379,11 +356,21 @@ int load_game_from_file(const char *filename) while (fgets(buffer, sizeof(buffer), file) != NULL) { + if (step_count >= MAX_STEPS) + { + break; // 防止数组越界 + } if (sscanf(buffer, "%d,%d,%d,%d", &step_num, &steps[step_count].player, &steps[step_count].x, &steps[step_count].y) == 4) { // 将1-based坐标转换为0-based坐标 steps[step_count].x--; steps[step_count].y--; + // 验证坐标合法性 + if (steps[step_count].x < 0 || steps[step_count].x >= size || + steps[step_count].y < 0 || steps[step_count].y >= size) + { + continue; // 跳过非法坐标 + } step_count++; } }