diff --git a/ai.c b/ai.c index 7bb45f5..5c639f4 100644 --- a/ai.c +++ b/ai.c @@ -7,102 +7,102 @@ #include /** - * @brief 评估一个落子位置的综合得分(结合进攻和防守) - * @param x 行坐标 - * @param y 列坐标 - * @return int 综合得分 + * @brief 璇勪及涓涓惤瀛愪綅缃殑缁煎悎寰楀垎锛堢粨鍚堣繘鏀诲拰闃插畧锛 + * @param x 琛屽潗鏍 + * @param y 鍒楀潗鏍 + * @return int 缁煎悎寰楀垎 */ int evaluate_move(int x, int y) { - // 进攻得分:评估AI在此处落子的分数 + // 杩涙敾寰楀垎锛氳瘎浼癆I鍦ㄦ澶勮惤瀛愮殑鍒嗘暟 int attack_score = evaluate_pos(x, y, AI); - // 防守得分:评估玩家在此处落子的分数,作为防守的依据 + // 闃插畧寰楀垎锛氳瘎浼扮帺瀹跺湪姝ゅ钀藉瓙鐨勫垎鏁帮紝浣滀负闃插畧鐨勪緷鎹 int defense_score = evaluate_pos(x, y, PLAYER); - // 综合得分,防守权重由 defense_coefficient 控制 + // 缁煎悎寰楀垎锛岄槻瀹堟潈閲嶇敱 defense_coefficient 鎺у埗 return attack_score + (int)(defense_score * defense_coefficient); } /** - * @brief 评估特定位置对当前玩家的战略价值 - * @param x 行坐标(0-base) - * @param y 列坐标(0-base) - * @param player 玩家标识(PLAYER/AI) - * @return int 综合评估分数(越高表示位置越好) - * @note 评分标准: - * - 活四:100000 冲四:10000 死四:500 - * - 活三:5000 眠三:1000 死三:50 - * - 活二:500 眠二:100 死二:10 - * - 单子:50(开放)/10(半开放)/1(封闭) - * - 中心位置有额外加成 + * @brief 璇勪及鐗瑰畾浣嶇疆瀵瑰綋鍓嶇帺瀹剁殑鎴樼暐浠峰 + * @param x 琛屽潗鏍(0-base) + * @param y 鍒楀潗鏍(0-base) + * @param player 鐜╁鏍囪瘑(PLAYER/AI) + * @return int 缁煎悎璇勪及鍒嗘暟(瓒婇珮琛ㄧず浣嶇疆瓒婂ソ) + * @note 璇勫垎鏍囧噯: + * - 娲诲洓:100000 鍐插洓:10000 姝诲洓:500 + * - 娲讳笁:5000 鐪犱笁:1000 姝讳笁:50 + * - 娲讳簩:500 鐪犱簩:100 姝讳簩:10 + * - 鍗曞瓙:50(寮鏀)/10(鍗婂紑鏀)/1(灏侀棴) + * - 涓績浣嶇疆鏈夐澶栧姞鎴 */ int evaluate_pos(int x, int y, int player) { - // 保存原始值用于还原 + // 淇濆瓨鍘熷鍊肩敤浜庤繕鍘 int original = board[x][y]; - // 模拟在该位置落子 + // 妯℃嫙鍦ㄨ浣嶇疆钀藉瓙 board[x][y] = player; - int total_score = 0; // 总分 - int line_scores[4] = {0}; // 四个方向的得分 + int total_score = 0; // 鎬诲垎 + int line_scores[4] = {0}; // 鍥涗釜鏂瑰悜鐨勫緱鍒 - // 遍历四个方向进行评估 + // 閬嶅巻鍥涗釜鏂瑰悜杩涜璇勪及 for (int i = 0; i < 4; i++) { int dx = direction[i][0], dy = direction[i][1]; - // 获取当前方向上的棋型信息 + // 鑾峰彇褰撳墠鏂瑰悜涓婄殑妫嬪瀷淇℃伅 DirInfo info = count_specific_direction(x, y, dx, dy, player); - // 直接形成五连珠为必胜 + // 鐩存帴褰㈡垚浜旇繛鐝犱负蹇呰儨 if (info.continuous_chess >= 5) { - board[x][y] = original; // 还原棋盘 - return SEARCH_WIN_BONUS; // 返回最大分 + board[x][y] = original; // 杩樺師妫嬬洏 + return SEARCH_WIN_BONUS; // 杩斿洖鏈澶у垎 } - // 根据连续棋子数评分 + // 鏍规嵁杩炵画妫嬪瓙鏁拌瘎鍒 switch (info.continuous_chess) { - case 4: // 四连珠 - if (info.check_start && info.check_end) // 活四(两端开放) + case 4: // 鍥涜繛鐝 + if (info.check_start && info.check_end) // 娲诲洓(涓ょ寮鏀) line_scores[i] = AI_SCORE_LIVE_FOUR; - else if (info.check_start || info.check_end) // 冲四(一端开放) + else if (info.check_start || info.check_end) // 鍐插洓(涓绔紑鏀) line_scores[i] = AI_SCORE_RUSH_FOUR; - else // 死四(两端封闭) + else // 姝诲洓(涓ょ灏侀棴) line_scores[i] = AI_SCORE_DEAD_FOUR; break; - case 3: // 三连珠 - if (info.check_start && info.check_end) // 活三 + case 3: // 涓夎繛鐝 + if (info.check_start && info.check_end) // 娲讳笁 line_scores[i] = AI_SCORE_LIVE_THREE; - else if (info.check_start || info.check_end) // 眠三 + else if (info.check_start || info.check_end) // 鐪犱笁 line_scores[i] = AI_SCORE_SLEEP_THREE; - else // 死三 + else // 姝讳笁 line_scores[i] = AI_SCORE_DEAD_THREE; break; - case 2: // 二连珠 - if (info.check_start && info.check_end) // 活二 + case 2: // 浜岃繛鐝 + if (info.check_start && info.check_end) // 娲讳簩 line_scores[i] = AI_SCORE_LIVE_TWO; - else if (info.check_start || info.check_end) // 眠二 + else if (info.check_start || info.check_end) // 鐪犱簩 line_scores[i] = AI_SCORE_SLEEP_TWO; - else // 死二 + else // 姝讳簩 line_scores[i] = AI_SCORE_DEAD_TWO; break; - case 1: // 单子 - if (info.check_start && info.check_end) // 开放位置 + case 1: // 鍗曞瓙 + if (info.check_start && info.check_end) // 寮鏀句綅缃 line_scores[i] = AI_SCORE_LIVE_ONE; - else if (info.check_start || info.check_end) // 半开放位置 + else if (info.check_start || info.check_end) // 鍗婂紑鏀句綅缃 line_scores[i] = AI_SCORE_HALF_ONE; - else // 封闭位置 + else // 灏侀棴浣嶇疆 line_scores[i] = AI_SCORE_DEAD_ONE; break; } } - // 计算总分(最高方向分+其他方向分加权) + // 璁$畻鎬诲垎锛堟渶楂樻柟鍚戝垎+鍏朵粬鏂瑰悜鍒嗗姞鏉冿級 int max_score = 0; int sum_score = 0; for (int i = 0; i < 4; i++) @@ -113,44 +113,44 @@ int evaluate_pos(int x, int y, int player) } sum_score += line_scores[i]; } - total_score = max_score * 10 + sum_score; // 主方向权重更高 + total_score = max_score * 10 + sum_score; // 涓绘柟鍚戞潈閲嶆洿楂 - // 位置奖励:越靠近中心分数越高 + // 浣嶇疆濂栧姳锛氳秺闈犺繎涓績鍒嗘暟瓒婇珮 int center_x = BOARD_SIZE / 2; int center_y = BOARD_SIZE / 2; - int distance = abs(x - center_x) + abs(y - center_y); // 曼哈顿距离 - int position_bonus = AI_POSITION_BONUS_FACTOR * (BOARD_SIZE - distance); // 距离中心越近奖励越高 + int distance = abs(x - center_x) + abs(y - center_y); // 鏇煎搱椤胯窛绂 + int position_bonus = AI_POSITION_BONUS_FACTOR * (BOARD_SIZE - distance); // 璺濈涓績瓒婅繎濂栧姳瓒婇珮 - board[x][y] = original; // 还原棋盘状态 - return total_score + position_bonus; // 返回总评估分 + board[x][y] = original; // 杩樺師妫嬬洏鐘舵 + return total_score + position_bonus; // 杩斿洖鎬昏瘎浼板垎 } /** - * @brief 带α-β剪枝的深度优先搜索(极小极大算法实现) - * @param x 当前行坐标 - * @param y 当前列坐标 - * @param player 当前玩家 - * @param depth 剩余搜索深度 - * @param alpha α值(当前最大值) - * @param beta β值(当前最小值) - * @param is_maximizing 是否为极大化玩家(AI) - * @return int 最佳评估分数 - * @note 算法流程: - * 1. 检查是否获胜或达到搜索深度 - * 2. 遍历所有可能落子位置 - * 3. 递归评估每个位置的分数 - * 4. 根据is_maximizing选择最大/最小值 - * 5. 使用α-β剪枝优化搜索过程 + * @brief 甯ξ-尾鍓灊鐨勬繁搴︿紭鍏堟悳绱(鏋佸皬鏋佸ぇ绠楁硶瀹炵幇) + * @param x 褰撳墠琛屽潗鏍 + * @param y 褰撳墠鍒楀潗鏍 + * @param player 褰撳墠鐜╁ + * @param depth 鍓╀綑鎼滅储娣卞害 + * @param alpha 伪鍊(褰撳墠鏈澶у) + * @param beta 尾鍊(褰撳墠鏈灏忓) + * @param is_maximizing 鏄惁涓烘瀬澶у寲鐜╁(AI) + * @return int 鏈浣宠瘎浼板垎鏁 + * @note 绠楁硶娴佺▼: + * 1. 妫鏌ユ槸鍚﹁幏鑳滄垨杈惧埌鎼滅储娣卞害 + * 2. 閬嶅巻鎵鏈夊彲鑳借惤瀛愪綅缃 + * 3. 閫掑綊璇勪及姣忎釜浣嶇疆鐨勫垎鏁 + * 4. 鏍规嵁is_maximizing閫夋嫨鏈澶/鏈灏忓 + * 5. 浣跨敤伪-尾鍓灊浼樺寲鎼滅储杩囩▼ */ int dfs(int x, int y, int player, int depth, int alpha, int beta, bool is_maximizing) { - // 检查当前落子是否获胜 + // 妫鏌ュ綋鍓嶈惤瀛愭槸鍚﹁幏鑳 if (check_win(x, y, player)) { return (player == AI) ? SEARCH_WIN_BONUS + depth : -SEARCH_WIN_BONUS - depth; } - // 达到搜索深度或平局 + // 杈惧埌鎼滅储娣卞害鎴栧钩灞 if (depth == 0 || step_count >= BOARD_SIZE * BOARD_SIZE) { return evaluate_pos(x, y, AI) - evaluate_pos(x, y, PLAYER); @@ -158,7 +158,7 @@ int dfs(int x, int y, int player, int depth, int alpha, int beta, bool is_maximi int best_score = is_maximizing ? -1000000 : 1000000; - // 遍历所有可能落子位置 + // 閬嶅巻鎵鏈夊彲鑳借惤瀛愪綅缃 for (int i = 0; i < BOARD_SIZE; i++) { for (int j = 0; j < BOARD_SIZE; j++) @@ -168,34 +168,34 @@ int dfs(int x, int y, int player, int depth, int alpha, int beta, bool is_maximi continue; } - // 模拟当前玩家落子 + // 妯℃嫙褰撳墠鐜╁钀藉瓙 board[i][j] = player; step_count++; - // 递归搜索(切换玩家和搜索深度) + // 閫掑綊鎼滅储(鍒囨崲鐜╁鍜屾悳绱㈡繁搴) int current_score = dfs(i, j, (player == AI) ? PLAYER : AI, depth - 1, alpha, beta, !is_maximizing); - // 撤销落子 + // 鎾ら攢钀藉瓙 board[i][j] = EMPTY; step_count--; - // 极大值玩家(AI)逻辑 + // 鏋佸ぇ鍊肩帺瀹(AI)閫昏緫 if (is_maximizing) { best_score = (current_score > best_score) ? current_score : best_score; alpha = (best_score > alpha) ? best_score : alpha; - // α剪枝 + // 伪鍓灊 if (beta <= alpha) { break; } } - // 极小值玩家(人类)逻辑 + // 鏋佸皬鍊肩帺瀹(浜虹被)閫昏緫 else { best_score = (current_score < best_score) ? current_score : best_score; beta = (best_score < beta) ? best_score : beta; - // β剪枝 + // 尾鍓灊 if (beta <= alpha) { break; @@ -204,7 +204,7 @@ int dfs(int x, int y, int player, int depth, int alpha, int beta, bool is_maximi } if ((is_maximizing && best_score >= beta) || (!is_maximizing && best_score <= alpha)) { - break; // 提前退出外层循环 + break; // 鎻愬墠閫鍑哄灞傚惊鐜 } } @@ -212,28 +212,28 @@ int dfs(int x, int y, int player, int depth, int alpha, int beta, bool is_maximi } /** - * @brief AI决策主函数,使用评估函数和搜索算法选择最佳落子位置 - * @note 采用两阶段决策逻辑: - * 1. 防御阶段:检查并阻止玩家即将获胜的位置(活四、冲四、活三) - * 2. 进攻阶段:若无紧急防御需求,使用评估函数选择最佳进攻位置 - * @note 实现细节: - * - 优先处理玩家活四、冲四等危险局面 - * - 步数>AI_SEARCH_RANGE_THRESHOLD时缩小搜索范围到已有棋子附近AI_NEARBY_RANGE格 - * - 使用中心位置优先策略 + * @brief AI鍐崇瓥涓诲嚱鏁帮紝浣跨敤璇勪及鍑芥暟鍜屾悳绱㈢畻娉曢夋嫨鏈浣宠惤瀛愪綅缃 + * @note 閲囩敤涓ら樁娈靛喅绛栭昏緫锛 + * 1. 闃插尽闃舵锛氭鏌ュ苟闃绘鐜╁鍗冲皢鑾疯儨鐨勪綅缃紙娲诲洓銆佸啿鍥涖佹椿涓夛級 + * 2. 杩涙敾闃舵锛氳嫢鏃犵揣鎬ラ槻寰¢渶姹傦紝浣跨敤璇勪及鍑芥暟閫夋嫨鏈浣宠繘鏀讳綅缃 + * @note 瀹炵幇缁嗚妭锛 + * - 浼樺厛澶勭悊鐜╁娲诲洓銆佸啿鍥涚瓑鍗遍櫓灞闈 + * - 姝ユ暟>AI_SEARCH_RANGE_THRESHOLD鏃剁缉灏忔悳绱㈣寖鍥村埌宸叉湁妫嬪瓙闄勮繎AI_NEARBY_RANGE鏍 + * - 浣跨敤涓績浣嶇疆浼樺厛绛栫暐 */ void ai_move(int depth) { - // 如果是第一步,直接下在中心位置附近 + // 濡傛灉鏄涓姝ワ紝鐩存帴涓嬪湪涓績浣嶇疆闄勮繎 if (step_count == 0) { int center = BOARD_SIZE / 2; board[center][center] = AI; steps[step_count++] = (Step){AI, center, center}; - printf("AI落子(%d, %d)\n", center + 1, center + 1); + printf("AI钀藉瓙(%d, %d)\n", center + 1, center + 1); return; } - // 1. 首先检查是否需要阻止玩家的四子连棋或三子活棋 + // 1. 棣栧厛妫鏌ユ槸鍚﹂渶瑕侀樆姝㈢帺瀹剁殑鍥涘瓙杩炴鎴栦笁瀛愭椿妫 for (int i = 0; i < BOARD_SIZE; i++) { for (int j = 0; j < BOARD_SIZE; j++) @@ -243,23 +243,23 @@ void ai_move(int depth) continue; } - // 模拟玩家在此位置落子 + // 妯℃嫙鐜╁鍦ㄦ浣嶇疆钀藉瓙 board[i][j] = PLAYER; bool need_block = false; - // 检查四个方向 + // 妫鏌ュ洓涓柟鍚 for (int k = 0; k < 4; k++) { DirInfo info = count_specific_direction(i, j, direction[k][0], direction[k][1], PLAYER); - // 如果玩家能形成四子连棋且至少一端开放 + // 濡傛灉鐜╁鑳藉舰鎴愬洓瀛愯繛妫嬩笖鑷冲皯涓绔紑鏀 if (info.continuous_chess >= 4 && (info.check_start || info.check_end)) { need_block = true; break; } - // 如果玩家能形成三子活棋且两端开放 + // 濡傛灉鐜╁鑳藉舰鎴愪笁瀛愭椿妫嬩笖涓ょ寮鏀 if (info.continuous_chess == 3 && info.check_start && info.check_end) { need_block = true; @@ -267,24 +267,24 @@ void ai_move(int depth) } } - board[i][j] = EMPTY; // 恢复棋盘 + board[i][j] = EMPTY; // 鎭㈠妫嬬洏 if (need_block) { - // 必须在此位置落子阻止 + // 蹇呴』鍦ㄦ浣嶇疆钀藉瓙闃绘 board[i][j] = AI; steps[step_count++] = (Step){AI, i, j}; - printf("AI落子(%d, %d)\n", i + 1, j + 1); + printf("AI钀藉瓙(%d, %d)\n", i + 1, j + 1); return; } } } - // 2. 如果没有需要立即阻止的情况,则正常评估 + // 2. 濡傛灉娌℃湁闇瑕佺珛鍗抽樆姝㈢殑鎯呭喌锛屽垯姝e父璇勪及 int best_score = -SEARCH_WIN_BONUS; int best_x = -1, best_y = -1; - // 遍历棋盘所有空位 + // 閬嶅巻妫嬬洏鎵鏈夌┖浣 for (int i = 0; i < BOARD_SIZE; i++) { for (int j = 0; j < BOARD_SIZE; j++) @@ -294,7 +294,7 @@ void ai_move(int depth) continue; } - // 只考虑已有棋子附近(AI_NEARBY_RANGE格范围内) + // 鍙冭檻宸叉湁妫嬪瓙闄勮繎(AI_NEARBY_RANGE鏍艰寖鍥村唴) bool has_nearby_stone = false; for (int di = -AI_NEARBY_RANGE; di <= AI_NEARBY_RANGE; di++) { @@ -321,10 +321,10 @@ void ai_move(int depth) continue; } - // 使用评估函数获取综合得分 + // 浣跨敤璇勪及鍑芥暟鑾峰彇缁煎悎寰楀垎 int current_score = evaluate_move(i, j); - // 更新最佳位置 + // 鏇存柊鏈浣充綅缃 if (current_score > best_score) { best_score = current_score; @@ -334,11 +334,11 @@ void ai_move(int depth) } } - // 执行最佳落子 + // 鎵ц鏈浣宠惤瀛 if (best_x != -1 && best_y != -1) { board[best_x][best_y] = AI; steps[step_count++] = (Step){AI, best_x, best_y}; - printf("AI落子(%d, %d)\n", best_x + 1, best_y + 1); + printf("AI钀藉瓙(%d, %d)\n", best_x + 1, best_y + 1); } } \ No newline at end of file diff --git a/ai.h b/ai.h index 2255c37..87f9fe8 100644 --- a/ai.h +++ b/ai.h @@ -4,33 +4,33 @@ #include "gobang.h" /** - * @brief 评估一个落子位置的综合得分(结合进攻和防守) + * @brief 璇勪及涓涓惤瀛愪綅缃殑缁煎悎寰楀垎锛堢粨鍚堣繘鏀诲拰闃插畧锛 * - * @param x 行坐标 - * @param y 列坐标 - * @return int 综合得分 + * @param x 琛屽潗鏍 + * @param y 鍒楀潗鏍 + * @return int 缁煎悎寰楀垎 */ int evaluate_move(int x, int y); /** - * @brief 评估指定位置的价值 + * @brief 璇勪及鎸囧畾浣嶇疆鐨勪环鍊 * - * @param x 位置x坐标 - * @param y 位置y坐标 - * @param player 玩家标识(PLAYER/AI) - * @return int 位置价值 + * @param x 浣嶇疆x鍧愭爣 + * @param y 浣嶇疆y鍧愭爣 + * @param player 鐜╁鏍囪瘑(PLAYER/AI) + * @return int 浣嶇疆浠峰 */ int evaluate_pos(int x, int y, int player); /** - * @brief 评估棋盘价值 + * @brief 璇勪及妫嬬洏浠峰 * - * @param player 玩家标识(PLAYER/AI) + * @param player 鐜╁鏍囪瘑(PLAYER/AI) */ int dfs(int x, int y, int player, int depth, int alpha, int beta, bool is_maximizing); /** - * @brief AI下棋 + * @brief AI涓嬫 * * @param depth */ diff --git a/config.h b/config.h index 2c5bb7f..bcd92e2 100644 --- a/config.h +++ b/config.h @@ -1,151 +1,151 @@ /** * @file config.h - * @author 刘航宇(3364451258@qq.com、15236416560@163.com、lhy3364451258@outlook.com) - * @brief 五子棋游戏参数配置头文件 + * @author 鍒樿埅瀹(3364451258@qq.com銆15236416560@163.com銆乴hy3364451258@outlook.com) + * @brief 浜斿瓙妫嬫父鎴忓弬鏁伴厤缃ご鏂囦欢 * @version 6.0 * @date 2025-07-10 * * @copyright Copyright (c) 2025 * - * @note 本文件集中定义了五子棋游戏的所有参数配置,便于统一管理和修改 + * @note 鏈枃浠堕泦涓畾涔変簡浜斿瓙妫嬫父鎴忕殑鎵鏈夊弬鏁伴厤缃紝渚夸簬缁熶竴绠$悊鍜屼慨鏀 */ #ifndef CONFIG_H #define CONFIG_H -//---------- 棋盘相关参数 ----------// -#define MAX_BOARD_SIZE 25 // 支持的最大棋盘尺寸 -#define MIN_BOARD_SIZE 5 // 支持的最小棋盘尺寸 -#define DEFAULT_BOARD_SIZE 15 // 默认棋盘尺寸 -#define MAX_STEPS (MAX_BOARD_SIZE * MAX_BOARD_SIZE) // 游戏最大步数 +//---------- 妫嬬洏鐩稿叧鍙傛暟 ----------// +#define MAX_BOARD_SIZE 25 // 鏀寔鐨勬渶澶ф鐩樺昂瀵 +#define MIN_BOARD_SIZE 5 // 鏀寔鐨勬渶灏忔鐩樺昂瀵 +#define DEFAULT_BOARD_SIZE 15 // 榛樿妫嬬洏灏哄 +#define MAX_STEPS (MAX_BOARD_SIZE * MAX_BOARD_SIZE) // 娓告垙鏈澶ф鏁 -//---------- 玩家标识参数 ----------// -#define EMPTY 0 // 棋盘空位标识 -#define PLAYER 1 // 玩家标识 (用于人机对战模式) -#define AI 2 // AI标识 (用于人机对战模式) -#define PLAYER1 1 // 玩家1标识 (用于双人对战模式) -#define PLAYER2 2 // 玩家2标识 (用于双人对战模式) +//---------- 鐜╁鏍囪瘑鍙傛暟 ----------// +#define EMPTY 0 // 妫嬬洏绌轰綅鏍囪瘑 +#define PLAYER 1 // 鐜╁鏍囪瘑 (鐢ㄤ簬浜烘満瀵规垬妯″紡) +#define AI 2 // AI鏍囪瘑 (鐢ㄤ簬浜烘満瀵规垬妯″紡) +#define PLAYER1 1 // 鐜╁1鏍囪瘑 (鐢ㄤ簬鍙屼汉瀵规垬妯″紡) +#define PLAYER2 2 // 鐜╁2鏍囪瘑 (鐢ㄤ簬鍙屼汉瀵规垬妯″紡) -//---------- 特殊输入命令 ----------// -#define INPUT_UNDO -1 // 悔棋 -#define INPUT_SAVE -2 // 保存 -#define INPUT_EXIT -3 // 退出 -#define INPUT_SURRENDER -4 // 认输 +//---------- 鐗规畩杈撳叆鍛戒护 ----------// +#define INPUT_UNDO -1 // 鎮旀 +#define INPUT_SAVE -2 // 淇濆瓨 +#define INPUT_EXIT -3 // 閫鍑 +#define INPUT_SURRENDER -4 // 璁よ緭 -//---------- 游戏设置默认值 ----------// -#define DEFAULT_USE_FORBIDDEN_MOVES false // 默认不启用禁手规则 -#define DEFAULT_USE_TIMER 0 // 默认不启用计时器 -#define DEFAULT_TIME_LIMIT 30 // 默认时间限制为30秒(内部存储) +//---------- 娓告垙璁剧疆榛樿鍊 ----------// +#define DEFAULT_USE_FORBIDDEN_MOVES false // 榛樿涓嶅惎鐢ㄧ鎵嬭鍒 +#define DEFAULT_USE_TIMER 0 // 榛樿涓嶅惎鐢ㄨ鏃跺櫒 +#define DEFAULT_TIME_LIMIT 30 // 榛樿鏃堕棿闄愬埗涓30绉(鍐呴儴瀛樺偍) -//---------- AI参数 ----------// -#define DEFAULT_AI_DEPTH 3 // 默认AI搜索深度 -#define DEFAULT_DEFENSE_COEFFICIENT 1.2 // 默认防守系数 +//---------- AI鍙傛暟 ----------// +#define DEFAULT_AI_DEPTH 3 // 榛樿AI鎼滅储娣卞害 +#define DEFAULT_DEFENSE_COEFFICIENT 1.2 // 榛樿闃插畧绯绘暟 -//---------- 网络参数 ----------// -#define DEFAULT_NETWORK_PORT 8888 // 默认网络端口 -#define MIN_NETWORK_PORT 1024 // 最小网络端口 -#define MAX_NETWORK_PORT 65535 // 最大网络端口 -#define NETWORK_TIMEOUT_MS 5000 // 网络超时时间(毫秒) -#define NETWORK_BUFFER_SIZE 1024 // 网络缓冲区大小 +//---------- 缃戠粶鍙傛暟 ----------// +#define DEFAULT_NETWORK_PORT 8888 // 榛樿缃戠粶绔彛 +#define MIN_NETWORK_PORT 1024 // 鏈灏忕綉缁滅鍙 +#define MAX_NETWORK_PORT 65535 // 鏈澶х綉缁滅鍙 +#define NETWORK_TIMEOUT_MS 5000 // 缃戠粶瓒呮椂鏃堕棿(姣) +#define NETWORK_BUFFER_SIZE 1024 // 缃戠粶缂撳啿鍖哄ぇ灏 -//---------- 评分参数 ----------// -// 棋型评分 - 用于calculate_step_score函数 -#define SCORE_FIVE 0 // 五连 -#define SCORE_LIVE_FOUR 2000 // 活四 -#define SCORE_RUSH_FOUR 1000 // 冲四 -#define SCORE_DEAD_FOUR 300 // 死四 -#define SCORE_LIVE_THREE 500 // 活三 -#define SCORE_SLEEP_THREE 200 // 眠三 -#define SCORE_DEAD_THREE 80 // 死三 -#define SCORE_LIVE_TWO 100 // 活二 -#define SCORE_SLEEP_TWO 40 // 眠二 -#define SCORE_DEAD_TWO 15 // 死二 -#define SCORE_LIVE_ONE 15 // 开放单子 -#define SCORE_HALF_ONE 8 // 半开放单子 -#define SCORE_DEAD_ONE 2 // 封闭单子 +//---------- 璇勫垎鍙傛暟 ----------// +// 妫嬪瀷璇勫垎 - 鐢ㄤ簬calculate_step_score鍑芥暟 +#define SCORE_FIVE 0 // 浜旇繛 +#define SCORE_LIVE_FOUR 2000 // 娲诲洓 +#define SCORE_RUSH_FOUR 1000 // 鍐插洓 +#define SCORE_DEAD_FOUR 300 // 姝诲洓 +#define SCORE_LIVE_THREE 500 // 娲讳笁 +#define SCORE_SLEEP_THREE 200 // 鐪犱笁 +#define SCORE_DEAD_THREE 80 // 姝讳笁 +#define SCORE_LIVE_TWO 100 // 娲讳簩 +#define SCORE_SLEEP_TWO 40 // 鐪犱簩 +#define SCORE_DEAD_TWO 15 // 姝讳簩 +#define SCORE_LIVE_ONE 15 // 寮鏀惧崟瀛 +#define SCORE_HALF_ONE 8 // 鍗婂紑鏀惧崟瀛 +#define SCORE_DEAD_ONE 2 // 灏侀棴鍗曞瓙 -// 位置奖励系数 -#define POSITION_BONUS_FACTOR 10 // 位置奖励因子 +// 浣嶇疆濂栧姳绯绘暟 +#define POSITION_BONUS_FACTOR 10 // 浣嶇疆濂栧姳鍥犲瓙 -// AI评估参数 - 用于evaluate_pos函数 -#define AI_SCORE_FIVE 1000000 // AI评估-五连 -#define AI_SCORE_LIVE_FOUR 100000 // AI评估-活四 -#define AI_SCORE_RUSH_FOUR 10000 // AI评估-冲四 -#define AI_SCORE_DEAD_FOUR 500 // AI评估-死四 -#define AI_SCORE_LIVE_THREE 5000 // AI评估-活三 -#define AI_SCORE_SLEEP_THREE 1000 // AI评估-眠三 -#define AI_SCORE_DEAD_THREE 50 // AI评估-死三 -#define AI_SCORE_LIVE_TWO 500 // AI评估-活二 -#define AI_SCORE_SLEEP_TWO 100 // AI评估-眠二 -#define AI_SCORE_DEAD_TWO 10 // AI评估-死二 -#define AI_SCORE_LIVE_ONE 50 // AI评估-开放单子 -#define AI_SCORE_HALF_ONE 10 // AI评估-半开放单子 -#define AI_SCORE_DEAD_ONE 1 // AI评估-封闭单子 +// AI璇勪及鍙傛暟 - 鐢ㄤ簬evaluate_pos鍑芥暟 +#define AI_SCORE_FIVE 1000000 // AI璇勪及-浜旇繛 +#define AI_SCORE_LIVE_FOUR 100000 // AI璇勪及-娲诲洓 +#define AI_SCORE_RUSH_FOUR 10000 // AI璇勪及-鍐插洓 +#define AI_SCORE_DEAD_FOUR 500 // AI璇勪及-姝诲洓 +#define AI_SCORE_LIVE_THREE 5000 // AI璇勪及-娲讳笁 +#define AI_SCORE_SLEEP_THREE 1000 // AI璇勪及-鐪犱笁 +#define AI_SCORE_DEAD_THREE 50 // AI璇勪及-姝讳笁 +#define AI_SCORE_LIVE_TWO 500 // AI璇勪及-娲讳簩 +#define AI_SCORE_SLEEP_TWO 100 // AI璇勪及-鐪犱簩 +#define AI_SCORE_DEAD_TWO 10 // AI璇勪及-姝讳簩 +#define AI_SCORE_LIVE_ONE 50 // AI璇勪及-寮鏀惧崟瀛 +#define AI_SCORE_HALF_ONE 10 // AI璇勪及-鍗婂紑鏀惧崟瀛 +#define AI_SCORE_DEAD_ONE 1 // AI璇勪及-灏侀棴鍗曞瓙 -// AI位置奖励系数 -#define AI_POSITION_BONUS_FACTOR 50 // AI位置奖励因子 +// AI浣嶇疆濂栧姳绯绘暟 +#define AI_POSITION_BONUS_FACTOR 50 // AI浣嶇疆濂栧姳鍥犲瓙 -// 搜索算法参数 -#define SEARCH_MAX_SCORE 1000000 // 搜索最大分数 -#define SEARCH_WIN_BONUS 1000000 // 获胜奖励分数 -#define AI_NEARBY_RANGE 2 // AI搜索的邻近范围 -#define AI_SEARCH_RANGE_THRESHOLD 10 // AI开始限制搜索范围的步数阈值 +// 鎼滅储绠楁硶鍙傛暟 +#define SEARCH_MAX_SCORE 1000000 // 鎼滅储鏈澶у垎鏁 +#define SEARCH_WIN_BONUS 1000000 // 鑾疯儨濂栧姳鍒嗘暟 +#define AI_NEARBY_RANGE 2 // AI鎼滅储鐨勯偦杩戣寖鍥 +#define AI_SEARCH_RANGE_THRESHOLD 10 // AI寮濮嬮檺鍒舵悳绱㈣寖鍥寸殑姝ユ暟闃堝 -// 评分权重参数 -#define TIME_WEIGHT_FACTOR 0.5 // 时间权重因子 -#define WIN_BONUS 2000 // 胜利奖励分数 +// 璇勫垎鏉冮噸鍙傛暟 +#define TIME_WEIGHT_FACTOR 0.5 // 鏃堕棿鏉冮噸鍥犲瓙 +#define WIN_BONUS 2000 // 鑳滃埄濂栧姳鍒嗘暟 -// 文件路径参数 -#define RECORDS_DIR "records" // 记录文件目录 -#define CONFIG_FILE "gobang_config.ini" // 配置文件路径 -#define MAX_PATH_LENGTH 256 // 最大路径长度 +// 鏂囦欢璺緞鍙傛暟 +#define RECORDS_DIR "records" // 璁板綍鏂囦欢鐩綍 +#define CONFIG_FILE "gobang_config.ini" // 閰嶇疆鏂囦欢璺緞 +#define MAX_PATH_LENGTH 256 // 鏈澶ц矾寰勯暱搴 -//---------- 配置管理函数声明 ----------// +//---------- 閰嶇疆绠$悊鍑芥暟澹版槑 ----------// /** - * @brief 加载游戏配置 + * @brief 鍔犺浇娓告垙閰嶇疆 */ void load_game_config(); /** - * @brief 保存游戏配置 + * @brief 淇濆瓨娓告垙閰嶇疆 */ void save_game_config(); /** - * @brief 重置为默认配置 + * @brief 閲嶇疆涓洪粯璁ら厤缃 */ void reset_to_default_config(); /** - * @brief 显示当前配置 + * @brief 鏄剧ず褰撳墠閰嶇疆 */ void display_current_config(); /** - * @brief 配置棋盘大小 + * @brief 閰嶇疆妫嬬洏澶у皬 */ void config_board_size(); /** - * @brief 配置禁手规则 + * @brief 閰嶇疆绂佹墜瑙勫垯 */ void config_forbidden_moves(); /** - * @brief 配置计时器 + * @brief 閰嶇疆璁℃椂鍣 */ void config_timer(); /** - * @brief 配置网络参数 + * @brief 閰嶇疆缃戠粶鍙傛暟 */ void config_network(); /** - * @brief 配置管理主菜单 + * @brief 閰嶇疆绠$悊涓昏彍鍗 */ void config_management_menu(); -//---------- 网络配置全局变量声明 ----------// 全局变量声明现在在globals.h中 +//---------- 缃戠粶閰嶇疆鍏ㄥ眬鍙橀噺澹版槑 ----------// 鍏ㄥ眬鍙橀噺澹版槑鐜板湪鍦╣lobals.h涓 #endif // CONFIG_H \ No newline at end of file diff --git a/gobang.c b/gobang.c index 091e161..702926f 100644 --- a/gobang.c +++ b/gobang.c @@ -10,19 +10,19 @@ #include /** - * @brief 检查棋盘(x, y)位置是否为空 - * @param x 行坐标(0-base) - * @param y 列坐标(0-base) - * @return true-空, false-非空 + * @brief 妫鏌ユ鐩(x, y)浣嶇疆鏄惁涓虹┖ + * @param x 琛屽潗鏍(0-base) + * @param y 鍒楀潗鏍(0-base) + * @return true-绌, false-闈炵┖ */ bool have_space(int x, int y) { return x >= 0 && x < BOARD_SIZE && y >= 0 && y < BOARD_SIZE && board[x][y] == EMPTY; } -// 函数定义 +// 鍑芥暟瀹氫箟 /** - * @brief 检查是否为禁手 + * @brief 妫鏌ユ槸鍚︿负绂佹墜 * * @param x * @param y @@ -53,7 +53,7 @@ bool is_forbidden_move(int x, int y, int player) if (info.continuous_chess > 5) { board[x][y] = EMPTY; - return true; // 长连禁手 + return true; // 闀胯繛绂佹墜 } if (info.continuous_chess == 3 && info.check_start && info.check_end) { @@ -69,64 +69,64 @@ bool is_forbidden_move(int x, int y, int player) if (three_count >= 2 || four_count >= 2) { - return true; // 三三或四四禁手 + return true; // 涓変笁鎴栧洓鍥涚鎵 } return false; } /** - * @brief 执行玩家落子操作 - * @param x 行坐标(0-base) - * @param y 列坐标(0-base) - * @return true 落子成功 - * @return false 落子失败(位置无效) + * @brief 鎵ц鐜╁钀藉瓙鎿嶄綔 + * @param x 琛屽潗鏍(0-base) + * @param y 鍒楀潗鏍(0-base) + * @return true 钀藉瓙鎴愬姛 + * @return false 钀藉瓙澶辫触(浣嶇疆鏃犳晥) */ bool player_move(int x, int y, int player) { - // 位置无效则返回false + // 浣嶇疆鏃犳晥鍒欒繑鍥瀎alse if (!have_space(x, y)) return false; if (is_forbidden_move(x, y, player)) { - printf("禁手!请选择其他位置。\n"); + printf("绂佹墜锛佽閫夋嫨鍏朵粬浣嶇疆銆俓n"); return false; } - // 更新棋盘状态 + // 鏇存柊妫嬬洏鐘舵 board[x][y] = player; - // 记录落子步骤:玩家标识和坐标 + // 璁板綍钀藉瓙姝ラ锛氱帺瀹舵爣璇嗗拰鍧愭爣 steps[step_count++] = (Step){player, x, y}; return true; } /** - * @brief 计算特定方向上连续同色棋子数量 - * @param x 起始行坐标 - * @param y 起始列坐标 - * @param dx 行方向增量(-1,0,1) - * @param dy 列方向增量(-1,0,1) - * @param player 玩家标识(PLAYER/AI) - * @return DirInfo 包含连续棋子数和方向开放状态的结构体 - * @note 检查正反两个方向,统计连续棋子数并判断端点是否开放 + * @brief 璁$畻鐗瑰畾鏂瑰悜涓婅繛缁悓鑹叉瀛愭暟閲 + * @param x 璧峰琛屽潗鏍 + * @param y 璧峰鍒楀潗鏍 + * @param dx 琛屾柟鍚戝閲(-1,0,1) + * @param dy 鍒楁柟鍚戝閲(-1,0,1) + * @param player 鐜╁鏍囪瘑(PLAYER/AI) + * @return DirInfo 鍖呭惈杩炵画妫嬪瓙鏁板拰鏂瑰悜寮鏀剧姸鎬佺殑缁撴瀯浣 + * @note 妫鏌ユ鍙嶄袱涓柟鍚戯紝缁熻杩炵画妫嬪瓙鏁板苟鍒ゆ柇绔偣鏄惁寮鏀 */ DirInfo count_specific_direction(int x, int y, int dx, int dy, int player) { DirInfo info; - info.continuous_chess = 1; // 起始位置已经有一个棋子 - info.check_start = false; // 起点方向是否开放 - info.check_end = false; // 终点方向是否开放 + info.continuous_chess = 1; // 璧峰浣嶇疆宸茬粡鏈変竴涓瀛 + info.check_start = false; // 璧风偣鏂瑰悜鏄惁寮鏀 + info.check_end = false; // 缁堢偣鏂瑰悜鏄惁寮鏀 - // 检查正方向(dx, dy) + // 妫鏌ユ鏂瑰悜锛坉x, dy锛 int nx = x + dx, ny = y + dy; while (nx >= 0 && nx < BOARD_SIZE && ny >= 0 && ny < BOARD_SIZE && board[nx][ny] == player) { - info.continuous_chess++; // 连续棋子计数增加 - nx += dx; // 沿当前方向前进 + info.continuous_chess++; // 杩炵画妫嬪瓙璁℃暟澧炲姞 + nx += dx; // 娌垮綋鍓嶆柟鍚戝墠杩 ny += dy; } - // 判断正方向端点是否开放(遇到空位) + // 鍒ゆ柇姝f柟鍚戠鐐规槸鍚﹀紑鏀撅紙閬囧埌绌轰綅锛 if (nx >= 0 && nx < BOARD_SIZE && ny >= 0 && ny < BOARD_SIZE) { if (board[nx][ny] == EMPTY) @@ -135,15 +135,15 @@ DirInfo count_specific_direction(int x, int y, int dx, int dy, int player) } } - // 检查反方向(-dx, -dy) + // 妫鏌ュ弽鏂瑰悜锛-dx, -dy锛 nx = x - dx, ny = y - dy; while (nx >= 0 && nx < BOARD_SIZE && ny >= 0 && ny < BOARD_SIZE && board[nx][ny] == player) { - info.continuous_chess++; // 连续棋子计数增加 - nx -= dx; // 沿相反方向前进 + info.continuous_chess++; // 杩炵画妫嬪瓙璁℃暟澧炲姞 + nx -= dx; // 娌跨浉鍙嶆柟鍚戝墠杩 ny -= dy; } - // 判断反方向端点是否开放(遇到空位) + // 鍒ゆ柇鍙嶆柟鍚戠鐐规槸鍚﹀紑鏀撅紙閬囧埌绌轰綅锛 if (nx >= 0 && nx < BOARD_SIZE && ny >= 0 && ny < BOARD_SIZE) { if (board[nx][ny] == EMPTY) @@ -157,24 +157,24 @@ DirInfo count_specific_direction(int x, int y, int dx, int dy, int player) bool check_win(int x, int y, int player) { - // 检查四个方向是否存在五连珠 + // 妫鏌ュ洓涓柟鍚戞槸鍚﹀瓨鍦ㄤ簲杩炵彔 for (int i = 0; i < 4; i++) { DirInfo info = count_specific_direction(x, y, direction[i][0], direction[i][1], player); - if (info.continuous_chess >= 5) // 连续棋子>=5即获胜 + if (info.continuous_chess >= 5) // 杩炵画妫嬪瓙>=5鍗宠幏鑳 { return true; } } - return false; // 四个方向都没有五连珠 + return false; // 鍥涗釜鏂瑰悜閮芥病鏈変簲杩炵彔 } /** - * @brief 悔棋功能实现 + * @brief 鎮旀鍔熻兘瀹炵幇 * - * @param steps_to_undo 要悔棋的步数 - * @return true 悔棋成功 - * @return false 悔棋失败(步数不足) + * @param steps_to_undo 瑕佹倲妫嬬殑姝ユ暟 + * @return true 鎮旀鎴愬姛 + * @return false 鎮旀澶辫触(姝ユ暟涓嶈冻) */ bool return_move(int steps_to_undo) { @@ -196,74 +196,74 @@ bool return_move(int steps_to_undo) } /** - * @brief 评估玩家在整盘棋局中的表现 - * @param player 要评估的玩家(PLAYER/AI) - * @return int 总分(已考虑方向重复计算) - * @note 改进后的评分标准: - * - 五连:5000 (提高权重,更强调获胜) - * - 活四:2000 冲四:1000 死四:300 (提高权重,强调进攻性) - * - 活三:500 眠三:200 死三:80 (提高权重,强调战略价值) - * - 活二:100 眠二:40 死二:15 (适当提高权重) - * - 开放单子:15 半开放单子:8 封闭单子:2 (适当提高权重) - * @note 实现细节: - * 1. 遍历棋盘所有位置 - * 2. 对每个棋子检查四个方向 - * 3. 统计所有连子情况并评分 - * 4. 最终分数除以4(消除方向重复计算影响) + * @brief 璇勪及鐜╁鍦ㄦ暣鐩樻灞涓殑琛ㄧ幇 + * @param player 瑕佽瘎浼扮殑鐜╁(PLAYER/AI) + * @return int 鎬诲垎(宸茶冭檻鏂瑰悜閲嶅璁$畻) + * @note 鏀硅繘鍚庣殑璇勫垎鏍囧噯: + * - 浜旇繛:5000 (鎻愰珮鏉冮噸锛屾洿寮鸿皟鑾疯儨) + * - 娲诲洓:2000 鍐插洓:1000 姝诲洓:300 (鎻愰珮鏉冮噸锛屽己璋冭繘鏀绘) + * - 娲讳笁:500 鐪犱笁:200 姝讳笁:80 (鎻愰珮鏉冮噸锛屽己璋冩垬鐣ヤ环鍊) + * - 娲讳簩:100 鐪犱簩:40 姝讳簩:15 (閫傚綋鎻愰珮鏉冮噸) + * - 寮鏀惧崟瀛:15 鍗婂紑鏀惧崟瀛:8 灏侀棴鍗曞瓙:2 (閫傚綋鎻愰珮鏉冮噸) + * @note 瀹炵幇缁嗚妭: + * 1. 閬嶅巻妫嬬洏鎵鏈変綅缃 + * 2. 瀵规瘡涓瀛愭鏌ュ洓涓柟鍚 + * 3. 缁熻鎵鏈夎繛瀛愭儏鍐靛苟璇勫垎 + * 4. 鏈缁堝垎鏁伴櫎浠4(娑堥櫎鏂瑰悜閲嶅璁$畻褰卞搷) */ int calculate_step_score(int x, int y, int player) { int step_score = 0; - // 检查四个方向 + // 妫鏌ュ洓涓柟鍚 for (int k = 0; k < 4; k++) { DirInfo info = count_specific_direction(x, y, direction[k][0], direction[k][1], player); - // 根据连子数评分 + // 鏍规嵁杩炲瓙鏁拌瘎鍒 switch (info.continuous_chess) { case 5: step_score += SCORE_FIVE; - break; // 五连 + break; // 浜旇繛 case 4: if (info.check_start && info.check_end) - step_score += SCORE_LIVE_FOUR; // 活四 + step_score += SCORE_LIVE_FOUR; // 娲诲洓 else if (info.check_start || info.check_end) - step_score += SCORE_RUSH_FOUR; // 冲四 + step_score += SCORE_RUSH_FOUR; // 鍐插洓 else - step_score += SCORE_DEAD_FOUR; // 死四 + step_score += SCORE_DEAD_FOUR; // 姝诲洓 break; case 3: if (info.check_start && info.check_end) - step_score += SCORE_LIVE_THREE; // 活三 + step_score += SCORE_LIVE_THREE; // 娲讳笁 else if (info.check_start || info.check_end) - step_score += SCORE_SLEEP_THREE; // 眠三 + step_score += SCORE_SLEEP_THREE; // 鐪犱笁 else - step_score += SCORE_DEAD_THREE; // 死三 + step_score += SCORE_DEAD_THREE; // 姝讳笁 break; case 2: if (info.check_start && info.check_end) - step_score += SCORE_LIVE_TWO; // 活二 + step_score += SCORE_LIVE_TWO; // 娲讳簩 else if (info.check_start || info.check_end) - step_score += SCORE_SLEEP_TWO; // 眠二 + step_score += SCORE_SLEEP_TWO; // 鐪犱簩 else - step_score += SCORE_DEAD_TWO; // 死二 + step_score += SCORE_DEAD_TWO; // 姝讳簩 break; case 1: if (info.check_start && info.check_end) - step_score += SCORE_LIVE_ONE; // 开放单子 + step_score += SCORE_LIVE_ONE; // 寮鏀惧崟瀛 else if (info.check_start || info.check_end) - step_score += SCORE_HALF_ONE; // 半开放单子 + step_score += SCORE_HALF_ONE; // 鍗婂紑鏀惧崟瀛 else - step_score += SCORE_DEAD_ONE; // 封闭单子 + step_score += SCORE_DEAD_ONE; // 灏侀棴鍗曞瓙 break; } } - // 位置奖励:越靠近中心分数越高 + // 浣嶇疆濂栧姳锛氳秺闈犺繎涓績鍒嗘暟瓒婇珮 int center_x = BOARD_SIZE / 2; int center_y = BOARD_SIZE / 2; - int distance = abs(x - center_x) + abs(y - center_y); // 曼哈顿距离 - int position_bonus = POSITION_BONUS_FACTOR * (BOARD_SIZE - distance); // 距离中心越近奖励越高 + int distance = abs(x - center_x) + abs(y - center_y); // 鏇煎搱椤胯窛绂 + int position_bonus = POSITION_BONUS_FACTOR * (BOARD_SIZE - distance); // 璺濈涓績瓒婅繎濂栧姳瓒婇珮 return step_score + position_bonus; } \ No newline at end of file diff --git a/gobang.h b/gobang.h index f6eaa1d..48ca98d 100644 --- a/gobang.h +++ b/gobang.h @@ -9,92 +9,92 @@ #include #include -// 数据结构 +// 鏁版嵁缁撴瀯 /** - * @brief 记录一步棋的详细信息 + * @brief 璁板綍涓姝ユ鐨勮缁嗕俊鎭 */ typedef struct { - int player; // 执行该步的玩家标识 - int x; // 落子的行坐标 (0-based) - int y; // 落子的列坐标 (0-based) + int player; // 鎵ц璇ユ鐨勭帺瀹舵爣璇 + int x; // 钀藉瓙鐨勮鍧愭爣 (0-based) + int y; // 钀藉瓙鐨勫垪鍧愭爣 (0-based) } Step; /** - * @brief 存储在特定方向上棋子连续性的信息 - * @details 用于评估棋形,例如判断活三、冲四等关键形态。 + * @brief 瀛樺偍鍦ㄧ壒瀹氭柟鍚戜笂妫嬪瓙杩炵画鎬х殑淇℃伅 + * @details 鐢ㄤ簬璇勪及妫嬪舰锛屼緥濡傚垽鏂椿涓夈佸啿鍥涚瓑鍏抽敭褰㈡併 */ typedef struct { - int continuous_chess; // 连续同色棋子的数量 - bool check_start; // 棋子序列的起始端是否为空位(即是否开放) - bool check_end; // 棋子序列的末尾端是否为空位(即是否开放) + int continuous_chess; // 杩炵画鍚岃壊妫嬪瓙鐨勬暟閲 + bool check_start; // 妫嬪瓙搴忓垪鐨勮捣濮嬬鏄惁涓虹┖浣嶏紙鍗虫槸鍚﹀紑鏀撅級 + bool check_end; // 妫嬪瓙搴忓垪鐨勬湯灏剧鏄惁涓虹┖浣嶏紙鍗虫槸鍚﹀紑鏀撅級 } DirInfo; -// 函数原型 +// 鍑芥暟鍘熷瀷 -// --- 游戏核心逻辑 --- +// --- 娓告垙鏍稿績閫昏緫 --- /** - * @brief 检查指定坐标是否为有效落子点(在棋盘内且为空) - * @param x 待检查的行坐标 (0-based) - * @param y 待检查的列坐标 (0-based) - * @return 若位置有效且为空则返回true,否则返回false + * @brief 妫鏌ユ寚瀹氬潗鏍囨槸鍚︿负鏈夋晥钀藉瓙鐐癸紙鍦ㄦ鐩樺唴涓斾负绌猴級 + * @param x 寰呮鏌ョ殑琛屽潗鏍 (0-based) + * @param y 寰呮鏌ョ殑鍒楀潗鏍 (0-based) + * @return 鑻ヤ綅缃湁鏁堜笖涓虹┖鍒欒繑鍥瀟rue锛屽惁鍒欒繑鍥瀎alse */ bool have_space(int x, int y); /** - * @brief 判断一个落子是否为禁手 - * @param x 落子的行坐标 (0-based) - * @param y 落子的列坐标 (0-based) - * @param player 当前玩家的标识 - * @return 如果是禁手则返回true,否则返回false + * @brief 鍒ゆ柇涓涓惤瀛愭槸鍚︿负绂佹墜 + * @param x 钀藉瓙鐨勮鍧愭爣 (0-based) + * @param y 钀藉瓙鐨勫垪鍧愭爣 (0-based) + * @param player 褰撳墠鐜╁鐨勬爣璇 + * @return 濡傛灉鏄鎵嬪垯杩斿洖true锛屽惁鍒欒繑鍥瀎alse */ bool is_forbidden_move(int x, int y, int player); /** - * @brief 执行一次玩家落子操作 - * @param x 落子的行坐标 (0-based) - * @param y 落子的列坐标 (0-based) - * @param player 当前玩家的标识 - * @return 若落子成功则返回true,否则(位置无效或被占用)返回false + * @brief 鎵ц涓娆$帺瀹惰惤瀛愭搷浣 + * @param x 钀藉瓙鐨勮鍧愭爣 (0-based) + * @param y 钀藉瓙鐨勫垪鍧愭爣 (0-based) + * @param player 褰撳墠鐜╁鐨勬爣璇 + * @return 鑻ヨ惤瀛愭垚鍔熷垯杩斿洖true锛屽惁鍒欙紙浣嶇疆鏃犳晥鎴栬鍗犵敤锛夎繑鍥瀎alse */ bool player_move(int x, int y, int player); /** - * @brief 计算在特定方向上的棋子连续信息 - * @param x 起始点的行坐标 - * @param y 起始点的列坐标 - * @param dx x方向的增量 (-1, 0, or 1) - * @param dy y方向的增量 (-1, 0, or 1) - * @param player 玩家标识 - * @return 返回一个包含连续棋子信息的 DirInfo 结构体 + * @brief 璁$畻鍦ㄧ壒瀹氭柟鍚戜笂鐨勬瀛愯繛缁俊鎭 + * @param x 璧峰鐐圭殑琛屽潗鏍 + * @param y 璧峰鐐圭殑鍒楀潗鏍 + * @param dx x鏂瑰悜鐨勫閲 (-1, 0, or 1) + * @param dy y鏂瑰悜鐨勫閲 (-1, 0, or 1) + * @param player 鐜╁鏍囪瘑 + * @return 杩斿洖涓涓寘鍚繛缁瀛愪俊鎭殑 DirInfo 缁撴瀯浣 */ DirInfo count_specific_direction(int x, int y, int dx, int dy, int player); /** - * @brief 检查在某点落子后,该玩家是否获胜 - * @param x 落子的行坐标 (0-based) - * @param y 落子的列坐标 (0-based) - * @param player 当前玩家的标识 - * @return 如果获胜则返回true,否则返回false + * @brief 妫鏌ュ湪鏌愮偣钀藉瓙鍚庯紝璇ョ帺瀹舵槸鍚﹁幏鑳 + * @param x 钀藉瓙鐨勮鍧愭爣 (0-based) + * @param y 钀藉瓙鐨勫垪鍧愭爣 (0-based) + * @param player 褰撳墠鐜╁鐨勬爣璇 + * @return 濡傛灉鑾疯儨鍒欒繑鍥瀟rue锛屽惁鍒欒繑鍥瀎alse */ bool check_win(int x, int y, int player); /** - * @brief 悔棋功能,撤销指定步数 - * @param steps_to_undo 要撤销的步数(每步包含双方各一次落子) - * @return 若悔棋成功则返回true,否则返回false + * @brief 鎮旀鍔熻兘锛屾挙閿鎸囧畾姝ユ暟 + * @param steps_to_undo 瑕佹挙閿鐨勬鏁帮紙姣忔鍖呭惈鍙屾柟鍚勪竴娆¤惤瀛愶級 + * @return 鑻ユ倲妫嬫垚鍔熷垯杩斿洖true锛屽惁鍒欒繑鍥瀎alse */ bool return_move(int steps_to_undo); /** - * @brief 计算并返回一步棋的得分 - * @param x 落子的行坐标 - * @param y 落子的列坐标 - * @param player 玩家标识 - * @return 该步棋的得分 + * @brief 璁$畻骞惰繑鍥炰竴姝ユ鐨勫緱鍒 + * @param x 钀藉瓙鐨勮鍧愭爣 + * @param y 钀藉瓙鐨勫垪鍧愭爣 + * @param player 鐜╁鏍囪瘑 + * @return 璇ユ妫嬬殑寰楀垎 */ int calculate_step_score(int x, int y, int player); diff --git a/init_board.c b/init_board.c index cb164da..465e03c 100644 --- a/init_board.c +++ b/init_board.c @@ -8,12 +8,12 @@ #include /** - * @brief 初始化棋盘为全空状态并重置步数计数器 - * 清空棋盘数组并将所有位置设为EMPTY,同时将step_count重置为0 + * @brief 鍒濆鍖栨鐩樹负鍏ㄧ┖鐘舵佸苟閲嶇疆姝ユ暟璁℃暟鍣 + * 娓呯┖妫嬬洏鏁扮粍骞跺皢鎵鏈変綅缃涓篍MPTY锛屽悓鏃跺皢step_count閲嶇疆涓0 */ void empty_board() { - // 初始化棋盘状态为全空 + // 鍒濆鍖栨鐩樼姸鎬佷负鍏ㄧ┖ for (int i = 0; i < BOARD_SIZE; i++) { for (int j = 0; j < BOARD_SIZE; j++) @@ -21,82 +21,82 @@ void empty_board() board[i][j] = EMPTY; } } - step_count = 0; // 重置步数计数器 + step_count = 0; // 閲嶇疆姝ユ暟璁℃暟鍣 } /** - * @brief 打印当前棋盘状态 - * 以可读格式输出棋盘,包括行列号和棋子状态 - * 玩家棋子显示为'x',AI棋子显示为'○',空位显示为'·' + * @brief 鎵撳嵃褰撳墠妫嬬洏鐘舵 + * 浠ュ彲璇绘牸寮忚緭鍑烘鐩橈紝鍖呮嫭琛屽垪鍙峰拰妫嬪瓙鐘舵 + * 鐜╁妫嬪瓙鏄剧ず涓'x'锛孉I妫嬪瓙鏄剧ず涓'鈼'锛岀┖浣嶆樉绀轰负'路' */ void print_board() { - // 打印列号(1-BOARD_SIZE显示) + // 鎵撳嵃鍒楀彿锛1-BOARD_SIZE鏄剧ず锛 printf("\n "); for (int i = 0; i < BOARD_SIZE; i++) { printf("%2d", i + 1); - if (i + 1 == 9) // 处理列号9和10+的对齐 + if (i + 1 == 9) // 澶勭悊鍒楀彿9鍜10+鐨勫榻 { printf(" "); } } printf("\n"); - // 逐行打印棋盘内容 + // 閫愯鎵撳嵃妫嬬洏鍐呭 for (int i = 0; i < BOARD_SIZE; i++) { - printf("%2d ", i + 1); // 打印行号(1-BOARD_SIZE) + printf("%2d ", i + 1); // 鎵撳嵃琛屽彿锛1-BOARD_SIZE锛 for (int j = 0; j < BOARD_SIZE; j++) { if (board[i][j] == PLAYER) { - printf("x "); // 玩家棋子 + printf("x "); // 鐜╁妫嬪瓙 } else if (board[i][j] == AI) { - printf("○ "); // AI棋子(使用○显示) + printf("鈼 "); // AI妫嬪瓙(浣跨敤鈼嬫樉绀) } else { - printf("· "); // 空位 + printf("路 "); // 绌轰綅 } } - printf("\n"); // 每行结束换行 + printf("\n"); // 姣忚缁撴潫鎹㈣ } } /** - * @brief 配置棋盘大小 + * @brief 閰嶇疆妫嬬洏澶у皬 * - * @param player1 玩家1 - * @param player2 玩家2 + * @param player1 鐜╁1 + * @param player2 鐜╁2 */ void setup_board_size() { - printf("通常棋盘大小分为休闲棋盘(13X13)、标准棋盘(15X15)和特殊棋盘(19X19)\n"); + printf("閫氬父妫嬬洏澶у皬鍒嗕负浼戦棽妫嬬洏(13X13)銆佹爣鍑嗘鐩(15X15)鍜岀壒娈婃鐩(19X19)\n"); char prompt[100]; - sprintf(prompt, "请输入棋盘大小(5~%d)(默认为标准棋盘):\n", MAX_BOARD_SIZE); + sprintf(prompt, "璇疯緭鍏ユ鐩樺ぇ灏(5~%d)(榛樿涓烘爣鍑嗘鐩):\n", MAX_BOARD_SIZE); BOARD_SIZE = get_integer_input(prompt, 5, MAX_BOARD_SIZE); } /** * @brief Set the up game options object - * 配置游戏选项,包括禁手规则、计时器和时间限制 + * 閰嶇疆娓告垙閫夐」锛屽寘鎷鎵嬭鍒欍佽鏃跺櫒鍜屾椂闂撮檺鍒 */ void setup_game_options() { - use_forbidden_moves = get_integer_input("是否启用禁手规则 (1-是, 0-否): ", 0, 1); + use_forbidden_moves = get_integer_input("鏄惁鍚敤绂佹墜瑙勫垯 (1-鏄, 0-鍚): ", 0, 1); - use_timer = get_integer_input("是否启用计时器 (1-是, 0-否): ", 0, 1); + use_timer = get_integer_input("鏄惁鍚敤璁℃椂鍣 (1-鏄, 0-鍚): ", 0, 1); if (use_timer) { - time_limit = get_integer_input("请输入每回合的时间限制 (1~60分钟): ", 1, 60) * 60; + time_limit = get_integer_input("璇疯緭鍏ユ瘡鍥炲悎鐨勬椂闂撮檺鍒 (1~60鍒嗛挓): ", 1, 60) * 60; } } /** - * @brief 确定先手玩家 + * @brief 纭畾鍏堟墜鐜╁ * * @param player1 * @param player2 @@ -105,7 +105,7 @@ void setup_game_options() int determine_first_player(int player1, int player2) { char prompt[100]; - sprintf(prompt, "请选择先手方 (1 for Player %d, 2 for Player %d): ", player1, player2); + sprintf(prompt, "璇烽夋嫨鍏堟墜鏂 (1 for Player %d, 2 for Player %d): ", player1, player2); int first_player_choice = get_integer_input(prompt, 1, 2); if (first_player_choice == 1) { diff --git a/main.c b/main.c index d394cd4..7864e1b 100644 --- a/main.c +++ b/main.c @@ -1,48 +1,3 @@ -/** - * @file 浜斿瓙妫.c - * @brief 浜斿瓙妫嬫父鎴忔牳蹇冮昏緫澶存枃浠 - * @details 娓告垙鏍稿績閫昏緫瀹炵幇 - * @author 鍒樿埅瀹(3364451258@qq.com銆15236416560@163.com銆乴hy3364451258@outlook.com) - * @date 2025-07-10 - * @version 6.0 - * @note - * 1. 鏂板鍔熻兘锛 - * - 澧炲姞浜嗗绂佹墜瑙勫垯鐨勬敮鎸侊紝闃叉鐜╁杩涜鏃犳剰涔夌殑璧版硶銆 - * - 鏂板浜嗘父鎴忚鏃跺櫒鍔熻兘锛岄檺鍒舵瘡鍥炲悎鐨勬濊冩椂闂淬 - * - 娣诲姞浜嗗鐩樺姛鑳斤紝鏀寔淇濆瓨鍜屽洖椤惧灞璁板綍銆 - * - 瀹炵幇浜嗚瘎鍒嗙郴缁燂紝鍙互瀵规瘡涓姝ユ杩涜璇勫垎鍜屽垎鏋愩 - * 2. 鎬ц兘浼樺寲锛 - * - 浼樺寲浜嗚瘎浼板嚱鏁扮殑鎬ц兘锛屽噺灏戜簡涓嶅繀瑕佺殑璁$畻銆 - * - 寮曞叆浜 Alpha-Beta 鍓灊绠楁硶锛屾彁楂樹簡 AI 鎼滅储鐨勬晥鐜囥 - * - 鏀硅繘浜嗗唴瀛樼鐞嗭紝鍑忓皯浜嗚祫婧愬崰鐢ㄣ - * 3. 鐢ㄦ埛鐣岄潰鏀硅繘锛 - * - 鏂板浜嗗懡浠よ鐣岄潰锛屾彁渚涙洿鍙嬪ソ鐨勪氦浜掍綋楠屻 - * - 鍙互鑷畾涔夋鐩樺ぇ灏忥紝澧炲姞娓告垙鐨勭伒娲绘с - * - 浼樺寲浜嗘彁绀轰俊鎭紝浣挎父鎴忔搷浣滄洿鍔犵洿瑙傘 - * 4. 浠g爜缁撴瀯浼樺寲锛 - * - 灏嗘父鎴忛昏緫鍜岀敤鎴风晫闈㈠垎绂伙紝鎻愰珮浠g爜鐨勫彲璇绘у拰鍙淮鎶ゆс - * - 浼樺寲浜嗕唬鐮佺粨鏋勶紝鎻愰珮浜嗕唬鐮佺殑鍙鎬у拰鍙淮鎶ゆс - * - 妯″潡鍖栬璁★紝渚夸簬鍔熻兘鎵╁睍鍜岀淮鎶ゃ - * 5. 寮傚父澶勭悊锛 - * - 澧炲姞浜嗚緭鍏ラ敊璇殑寮傚父澶勭悊鏈哄埗锛岀‘淇濇父鎴忕殑绋冲畾鎬с - * - 淇浜嗕竴浜涘凡鐭ョ殑 bug锛屾彁楂樻父鎴忕殑绋冲畾鎬с - * - 澧炲己浜嗛敊璇彁绀猴紝甯姪鐢ㄦ埛蹇熷畾浣嶉棶棰樸 - * 6. 鏂囨。鏇存柊锛 - * - 瀹屽杽浜嗕唬鐮佹敞閲婏紝鎻愰珮浜嗕唬鐮佺殑鍙鎬с - * - 鏇存柊浜嗘枃妗o紝鍖呮嫭鍔熻兘鎻忚堪銆佷娇鐢ㄦ柟娉曘佹敞鎰忎簨椤圭瓑銆 - * 7. 鐗堟湰鎺у埗锛 - * - 浣跨敤 Git 杩涜鐗堟湰鎺у埗锛屾柟渚垮洟闃熷崗浣滃拰浠g爜绠$悊銆 - * 8. 娴嬭瘯锛 - * - 杩涜浜嗗叏闈㈢殑娴嬭瘯锛岀‘淇濇父鎴忕殑绋冲畾鎬у拰鍔熻兘鐨勬纭с - * 9. 寮婧愬崗璁細 - * - 閫夋嫨浜 MIT 寮婧愬崗璁紝鍏佽鐢ㄦ埛鑷敱浣跨敤銆佷慨鏀瑰拰鍒嗗彂浠g爜銆 - * 10. 璐$尞鑰咃細 - * - 鍒樿埅瀹 - * 11. 鑱旂郴淇℃伅锛 - * - 椤圭洰涓婚〉锛歔https://github.com/LHY0125/Gobang-Game] - * - 鑱旂郴閭锛歔3364451258@qq.com][15236416560@163.com][lhy3364451258@outlook.com] - */ - #include "game_mode.h" #include "ui.h" #include "config.h" diff --git a/network.h b/network.h index 34cabc6..2086cb7 100644 --- a/network.h +++ b/network.h @@ -1,16 +1,16 @@ /** * @file network.h - * @author 刘航宇(3364451258@qq.com、15236416560@163.com、lhy3364451258@outlook.com) - * @brief 五子棋网络对战模块头文件 + * @author 鍒樿埅瀹(3364451258@qq.com銆15236416560@163.com銆乴hy3364451258@outlook.com) + * @brief 浜斿瓙妫嬬綉缁滃鎴樻ā鍧楀ご鏂囦欢 * @version 1.0 * @date 2025-01-15 * * @copyright Copyright (c) 2025 * - * @note 本文件定义了五子棋游戏的网络对战功能: - * 1. 服务器模式(主机) - * 2. 客户端模式(加入游戏) - * 3. 网络消息传输 + * @note 鏈枃浠跺畾涔変簡浜斿瓙妫嬫父鎴忕殑缃戠粶瀵规垬鍔熻兘锛 + * 1. 鏈嶅姟鍣ㄦā寮忥紙涓绘満锛 + * 2. 瀹㈡埛绔ā寮忥紙鍔犲叆娓告垙锛 + * 3. 缃戠粶娑堟伅浼犺緭 */ #ifndef NETWORK_H @@ -34,152 +34,152 @@ #define closesocket close #endif -// 网络配置 +// 缃戠粶閰嶇疆 #define DEFAULT_PORT 8888 #define BUFFER_SIZE 1024 #define MAX_IP_LENGTH 16 -// 消息类型 -#define MSG_MOVE 1 // 落子消息 -#define MSG_CHAT 2 // 聊天消息 -#define MSG_SURRENDER 3 // 认输消息 -#define MSG_UNDO_REQUEST 4 // 悔棋请求 -#define MSG_UNDO_RESPONSE 5 // 悔棋回应 -#define MSG_GAME_START 6 // 游戏开始 -#define MSG_GAME_END 7 // 游戏结束 -#define MSG_HEARTBEAT 8 // 心跳包 -#define MSG_DISCONNECT 9 // 断线消息 +// 娑堟伅绫诲瀷 +#define MSG_MOVE 1 // 钀藉瓙娑堟伅 +#define MSG_CHAT 2 // 鑱婂ぉ娑堟伅 +#define MSG_SURRENDER 3 // 璁よ緭娑堟伅 +#define MSG_UNDO_REQUEST 4 // 鎮旀璇锋眰 +#define MSG_UNDO_RESPONSE 5 // 鎮旀鍥炲簲 +#define MSG_GAME_START 6 // 娓告垙寮濮 +#define MSG_GAME_END 7 // 娓告垙缁撴潫 +#define MSG_HEARTBEAT 8 // 蹇冭烦鍖 +#define MSG_DISCONNECT 9 // 鏂嚎娑堟伅 -// 网络消息结构 +// 缃戠粶娑堟伅缁撴瀯 typedef struct { - int type; // 消息类型 - int player_id; // 玩家ID - int x, y; // 坐标(用于落子) - char message[256]; // 消息内容(用于聊天等) - time_t timestamp; // 时间戳 + int type; // 娑堟伅绫诲瀷 + int player_id; // 鐜╁ID + int x, y; // 鍧愭爣锛堢敤浜庤惤瀛愶級 + char message[256]; // 娑堟伅鍐呭锛堢敤浜庤亰澶╃瓑锛 + time_t timestamp; // 鏃堕棿鎴 } NetworkMessage; -// 网络游戏状态 +// 缃戠粶娓告垙鐘舵 typedef struct { - SOCKET socket; // 套接字 - bool is_server; // 是否为服务器 - bool is_connected; // 是否已连接 - int local_player_id; // 本地玩家ID - int remote_player_id; // 远程玩家ID - char remote_ip[MAX_IP_LENGTH]; // 远程IP地址 - int port; // 端口号 + SOCKET socket; // 濂楁帴瀛 + bool is_server; // 鏄惁涓烘湇鍔″櫒 + bool is_connected; // 鏄惁宸茶繛鎺 + int local_player_id; // 鏈湴鐜╁ID + int remote_player_id; // 杩滅▼鐜╁ID + char remote_ip[MAX_IP_LENGTH]; // 杩滅▼IP鍦板潃 + int port; // 绔彛鍙 } NetworkGameState; -// 全局变量声明现在在globals.h中 +// 鍏ㄥ眬鍙橀噺澹版槑鐜板湪鍦╣lobals.h涓 -// 函数声明 +// 鍑芥暟澹版槑 /** - * @brief 初始化网络模块 - * @return true 初始化成功 - * @return false 初始化失败 + * @brief 鍒濆鍖栫綉缁滄ā鍧 + * @return true 鍒濆鍖栨垚鍔 + * @return false 鍒濆鍖栧け璐 */ bool init_network(); /** - * @brief 清理网络模块 + * @brief 娓呯悊缃戠粶妯″潡 */ void cleanup_network(); /** - * @brief 创建服务器(主机模式) - * @param port 监听端口 - * @return true 创建成功 - * @return false 创建失败 + * @brief 鍒涘缓鏈嶅姟鍣紙涓绘満妯″紡锛 + * @param port 鐩戝惉绔彛 + * @return true 鍒涘缓鎴愬姛 + * @return false 鍒涘缓澶辫触 */ bool create_server(int port); /** - * @brief 连接到服务器(客户端模式) - * @param ip 服务器IP地址 - * @param port 服务器端口 - * @return true 连接成功 - * @return false 连接失败 + * @brief 杩炴帴鍒版湇鍔″櫒锛堝鎴风妯″紡锛 + * @param ip 鏈嶅姟鍣↖P鍦板潃 + * @param port 鏈嶅姟鍣ㄧ鍙 + * @return true 杩炴帴鎴愬姛 + * @return false 杩炴帴澶辫触 */ bool connect_to_server(const char* ip, int port); /** - * @brief 发送网络消息 - * @param msg 要发送的消息 - * @return true 发送成功 - * @return false 发送失败 + * @brief 鍙戦佺綉缁滄秷鎭 + * @param msg 瑕佸彂閫佺殑娑堟伅 + * @return true 鍙戦佹垚鍔 + * @return false 鍙戦佸け璐 */ bool send_network_message(const NetworkMessage* msg); /** - * @brief 接收网络消息 - * @param msg 接收消息的缓冲区 - * @param timeout_ms 超时时间(毫秒),0表示阻塞等待 - * @return true 接收成功 - * @return false 接收失败或超时 + * @brief 鎺ユ敹缃戠粶娑堟伅 + * @param msg 鎺ユ敹娑堟伅鐨勭紦鍐插尯 + * @param timeout_ms 瓒呮椂鏃堕棿锛堟绉掞級锛0琛ㄧず闃诲绛夊緟 + * @return true 鎺ユ敹鎴愬姛 + * @return false 鎺ユ敹澶辫触鎴栬秴鏃 */ bool receive_network_message(NetworkMessage* msg, int timeout_ms); /** - * @brief 断开网络连接 + * @brief 鏂紑缃戠粶杩炴帴 */ void disconnect_network(); /** - * @brief 检查网络连接状态 - * @return true 连接正常 - * @return false 连接断开 + * @brief 妫鏌ョ綉缁滆繛鎺ョ姸鎬 + * @return true 杩炴帴姝e父 + * @return false 杩炴帴鏂紑 */ bool is_network_connected(); /** - * @brief 获取本机IP地址 - * @param ip_buffer 存储IP地址的缓冲区 - * @param buffer_size 缓冲区大小 - * @return true 获取成功 - * @return false 获取失败 + * @brief 鑾峰彇鏈満IP鍦板潃 + * @param ip_buffer 瀛樺偍IP鍦板潃鐨勭紦鍐插尯 + * @param buffer_size 缂撳啿鍖哄ぇ灏 + * @return true 鑾峰彇鎴愬姛 + * @return false 鑾峰彇澶辫触 */ bool get_local_ip(char* ip_buffer, int buffer_size); /** - * @brief 发送落子消息 - * @param x 行坐标 - * @param y 列坐标 - * @param player_id 玩家ID - * @return true 发送成功 - * @return false 发送失败 + * @brief 鍙戦佽惤瀛愭秷鎭 + * @param x 琛屽潗鏍 + * @param y 鍒楀潗鏍 + * @param player_id 鐜╁ID + * @return true 鍙戦佹垚鍔 + * @return false 鍙戦佸け璐 */ bool send_move(int x, int y, int player_id); /** - * @brief 发送聊天消息 - * @param message 聊天内容 - * @return true 发送成功 - * @return false 发送失败 + * @brief 鍙戦佽亰澶╂秷鎭 + * @param message 鑱婂ぉ鍐呭 + * @return true 鍙戦佹垚鍔 + * @return false 鍙戦佸け璐 */ bool send_chat_message(const char* message); /** - * @brief 发送认输消息 - * @return true 发送成功 - * @return false 发送失败 + * @brief 鍙戦佽杈撴秷鎭 + * @return true 鍙戦佹垚鍔 + * @return false 鍙戦佸け璐 */ bool send_surrender(); /** - * @brief 发送悔棋请求 - * @param steps 悔棋步数 - * @return true 发送成功 - * @return false 发送失败 + * @brief 鍙戦佹倲妫嬭姹 + * @param steps 鎮旀姝ユ暟 + * @return true 鍙戦佹垚鍔 + * @return false 鍙戦佸け璐 */ bool send_undo_request(int steps); /** - * @brief 发送悔棋回应 - * @param accepted 是否同意悔棋 - * @param steps 悔棋步数 - * @return true 发送成功 - * @return false 发送失败 + * @brief 鍙戦佹倲妫嬪洖搴 + * @param accepted 鏄惁鍚屾剰鎮旀 + * @param steps 鎮旀姝ユ暟 + * @return true 鍙戦佹垚鍔 + * @return false 鍙戦佸け璐 */ bool send_undo_response(bool accepted, int steps); diff --git a/record.c b/record.c index 25a032a..fa30784 100644 --- a/record.c +++ b/record.c @@ -20,91 +20,91 @@ #endif /** - * @brief 复盘游戏全过程并展示评分 - * @note 实现流程: - * 1. 初始化临时复盘棋盘 - * 2. 按步数顺序逐步重现每个落子 - * 3. 每步显示: - * - 当前步数/总步数 - * - 落子方(玩家/AI) - * - 落子位置(1-based坐标) - * - 当前棋盘状态 - * 4. 通过用户按Enter键控制步骤前进 - * 5. 复盘结束后自动进入评分环节: - * - 评估双方表现 - * - 显示得分 - * - 评选MVP - * @note 技术细节: - * - 使用独立临时棋盘避免影响主游戏状态 - * - 坐标显示转换为1-based方便用户理解 - * - 包含输入缓冲区清理防止意外输入 - * - 评分环节调用calculate_final_score()函数 + * @brief 澶嶇洏娓告垙鍏ㄨ繃绋嬪苟灞曠ず璇勫垎 + * @note 瀹炵幇娴佺▼: + * 1. 鍒濆鍖栦复鏃跺鐩樻鐩 + * 2. 鎸夋鏁伴『搴忛愭閲嶇幇姣忎釜钀藉瓙 + * 3. 姣忔鏄剧ず: + * - 褰撳墠姝ユ暟/鎬绘鏁 + * - 钀藉瓙鏂(鐜╁/AI) + * - 钀藉瓙浣嶇疆(1-based鍧愭爣) + * - 褰撳墠妫嬬洏鐘舵 + * 4. 閫氳繃鐢ㄦ埛鎸塃nter閿帶鍒舵楠ゅ墠杩 + * 5. 澶嶇洏缁撴潫鍚庤嚜鍔ㄨ繘鍏ヨ瘎鍒嗙幆鑺: + * - 璇勪及鍙屾柟琛ㄧ幇 + * - 鏄剧ず寰楀垎 + * - 璇勯塎VP + * @note 鎶鏈粏鑺: + * - 浣跨敤鐙珛涓存椂妫嬬洏閬垮厤褰卞搷涓绘父鎴忕姸鎬 + * - 鍧愭爣鏄剧ず杞崲涓1-based鏂逛究鐢ㄦ埛鐞嗚В + * - 鍖呭惈杈撳叆缂撳啿鍖烘竻鐞嗛槻姝㈡剰澶栬緭鍏 + * - 璇勫垎鐜妭璋冪敤calculate_final_score()鍑芥暟 */ void review_process(int game_mode) { - int review_choice = get_integer_input("是否要复盘本局比赛? (1-是, 0-否): ", 0, 1); + int review_choice = get_integer_input("鏄惁瑕佸鐩樻湰灞姣旇禌? (1-鏄, 0-鍚): ", 0, 1); - // 如果评分尚未计算,则计算评分 + // 濡傛灉璇勫垎灏氭湭璁$畻锛屽垯璁$畻璇勫垎 if (!scores_calculated) { calculate_game_scores(); } else { - // 评分已从文件中加载,直接使用 - printf("从记录文件中加载评分数据\n"); + // 璇勫垎宸蹭粠鏂囦欢涓姞杞斤紝鐩存帴浣跨敤 + printf("浠庤褰曟枃浠朵腑鍔犺浇璇勫垎鏁版嵁\n"); } if (review_choice == 1) { - printf("\n===== 复盘记录(总步数:%d) =====\n", step_count); - // 清空输入缓冲区 + printf("\n===== 澶嶇洏璁板綍(鎬绘鏁帮細%d) =====\n", step_count); + // 娓呯┖杈撳叆缂撳啿鍖 int c; while ((c = getchar()) != '\n' && c != EOF) ; - // 创建临时复盘棋盘 + // 鍒涘缓涓存椂澶嶇洏妫嬬洏 int temp_board[MAX_BOARD_SIZE][MAX_BOARD_SIZE]; - memset(temp_board, EMPTY, sizeof(temp_board)); // 初始化为空棋盘 + memset(temp_board, EMPTY, sizeof(temp_board)); // 鍒濆鍖栦负绌烘鐩 - // 逐步重现游戏过程 + // 閫愭閲嶇幇娓告垙杩囩▼ for (int i = 0; i < step_count; i++) { - Step s = steps[i]; // 获取当前步骤 - temp_board[s.x][s.y] = s.player; // 在临时棋盘上落子 + Step s = steps[i]; // 鑾峰彇褰撳墠姝ラ + temp_board[s.x][s.y] = s.player; // 鍦ㄤ复鏃舵鐩樹笂钀藉瓙 - // 打印当前步骤信息 - // 根据游戏模式显示不同的标题和玩家信息 + // 鎵撳嵃褰撳墠姝ラ淇℃伅 + // 鏍规嵁娓告垙妯″紡鏄剧ず涓嶅悓鐨勬爣棰樺拰鐜╁淇℃伅 if (game_mode == 1) { - // 人机对战 - printf("\n===== 五子棋人机对战(%dX%d棋盘) =====", BOARD_SIZE, BOARD_SIZE); - printf("\n 第%d步/%d步: %s 落子于(%d, %d)\n", + // 浜烘満瀵规垬 + printf("\n===== 浜斿瓙妫嬩汉鏈哄鎴(%dX%d妫嬬洏) =====", BOARD_SIZE, BOARD_SIZE); + printf("\n 绗%d姝/%d姝: %s 钀藉瓙浜(%d, %d)\n", i + 1, step_count, - (s.player == PLAYER) ? "玩家" : "AI", + (s.player == PLAYER) ? "鐜╁" : "AI", s.x + 1, s.y + 1); } else { - // 双人对战 - printf("\n===== 五子棋双人对战(%dX%d棋盘) =====", BOARD_SIZE, BOARD_SIZE); - printf("\n 第%d步/%d步: %s 落子于(%d, %d)\n", + // 鍙屼汉瀵规垬 + printf("\n===== 浜斿瓙妫嬪弻浜哄鎴(%dX%d妫嬬洏) =====", BOARD_SIZE, BOARD_SIZE); + printf("\n 绗%d姝/%d姝: %s 钀藉瓙浜(%d, %d)\n", i + 1, step_count, - (s.player == PLAYER1) ? "玩家1(黑棋)" : "玩家2(白棋)", + (s.player == PLAYER1) ? "鐜╁1(榛戞)" : "鐜╁2(鐧芥)", s.x + 1, s.y + 1); } - // 打印当前复盘棋盘 + // 鎵撳嵃褰撳墠澶嶇洏妫嬬洏 printf(" "); for (int col = 0; col < BOARD_SIZE; col++) { - printf("%2d", col + 1); // 列号 + printf("%2d", col + 1); // 鍒楀彿 } printf("\n"); for (int row = 0; row < BOARD_SIZE; row++) { - printf("%2d ", row + 1); // 行号 + printf("%2d ", row + 1); // 琛屽彿 for (int col = 0; col < BOARD_SIZE; col++) { if (temp_board[row][col] == PLAYER || temp_board[row][col] == PLAYER1) @@ -113,72 +113,72 @@ void review_process(int game_mode) } else if (temp_board[row][col] == AI || temp_board[row][col] == PLAYER2) { - printf("○ "); + printf("鈼 "); } else { - printf("· "); + printf("路 "); } } - printf("\n"); // 行结束换行 + printf("\n"); // 琛岀粨鏉熸崲琛 } - // 如果不是最后一步,等待用户按键继续 + // 濡傛灉涓嶆槸鏈鍚庝竴姝ワ紝绛夊緟鐢ㄦ埛鎸夐敭缁х画 if (i < step_count - 1) { - printf("\n按Enter继续下一步..."); + printf("\n鎸塃nter缁х画涓嬩竴姝..."); while (getchar() != '\n') - ; // 等待回车 + ; // 绛夊緟鍥炶溅 } } - // 显示胜负结果(直接使用文件中的信息) - printf("\n===== 对局结果 ====="); - if (strcmp(winner_info, "玩家获胜") == 0) + // 鏄剧ず鑳滆礋缁撴灉锛堢洿鎺ヤ娇鐢ㄦ枃浠朵腑鐨勪俊鎭級 + printf("\n===== 瀵瑰眬缁撴灉 ====="); + if (strcmp(winner_info, "鐜╁鑾疯儨") == 0) { - printf("\n? 恭喜!玩家获胜!\n"); + printf("\n? 鎭枩锛佺帺瀹惰幏鑳滐紒\n"); } - else if (strcmp(winner_info, "AI获胜") == 0) + else if (strcmp(winner_info, "AI鑾疯儨") == 0) { - printf("\n? AI获胜!\n"); + printf("\n? AI鑾疯儨锛乗n"); } - else if (strcmp(winner_info, "玩家1获胜") == 0) + else if (strcmp(winner_info, "鐜╁1鑾疯儨") == 0) { - printf("\n? 恭喜!玩家1(黑棋)获胜!\n"); + printf("\n? 鎭枩锛佺帺瀹1(榛戞)鑾疯儨锛乗n"); } - else if (strcmp(winner_info, "玩家2获胜") == 0) + else if (strcmp(winner_info, "鐜╁2鑾疯儨") == 0) { - printf("\n? 恭喜!玩家2(白棋)获胜!\n"); + printf("\n? 鎭枩锛佺帺瀹2(鐧芥)鑾疯儨锛乗n"); } else { - printf("\n?? 对局平局或未完成\n"); + printf("\n?? 瀵瑰眬骞冲眬鎴栨湭瀹屾垚\n"); } - printf("\n复盘结束!按Enter查看评分..."); - getchar(); // 等待用户按键 + printf("\n澶嶇洏缁撴潫锛佹寜Enter鏌ョ湅璇勫垎..."); + getchar(); // 绛夊緟鐢ㄦ埛鎸夐敭 } - // 显示评分结果 + // 鏄剧ず璇勫垎缁撴灉 display_game_scores(game_mode); getchar(); } /** - * @brief 计算游戏评分 + * @brief 璁$畻娓告垙璇勫垎 */ void calculate_game_scores() { - // 评估双方表现 + // 璇勪及鍙屾柟琛ㄧ幇 player1_final_score = 0; player2_final_score = 0; - // 遍历所有步数,累积每一步的得分,后期步骤权重更高 + // 閬嶅巻鎵鏈夋鏁帮紝绱Н姣忎竴姝ョ殑寰楀垎锛屽悗鏈熸楠ゆ潈閲嶆洿楂 for (int i = 0; i < step_count; i++) { - // 计算时间权重因子:步数越靠后,权重越大 - double time_weight = 1.0 + (double)i / step_count * TIME_WEIGHT_FACTOR; // 最后的步骤权重是开始步骤的(1+TIME_WEIGHT_FACTOR)倍 + // 璁$畻鏃堕棿鏉冮噸鍥犲瓙锛氭鏁拌秺闈犲悗锛屾潈閲嶈秺澶 + double time_weight = 1.0 + (double)i / step_count * TIME_WEIGHT_FACTOR; // 鏈鍚庣殑姝ラ鏉冮噸鏄紑濮嬫楠ょ殑(1+TIME_WEIGHT_FACTOR)鍊 if (steps[i].player == PLAYER || steps[i].player == PLAYER1) { @@ -190,50 +190,50 @@ void calculate_game_scores() } } - // 胜负加权:获胜方获得额外的评分奖励 + // 鑳滆礋鍔犳潈锛氳幏鑳滄柟鑾峰緱棰濆鐨勮瘎鍒嗗鍔 if (step_count > 0) { Step last_step = steps[step_count - 1]; if (check_win(last_step.x, last_step.y, last_step.player)) { - // 获胜方获得额外奖励分数 + // 鑾疯儨鏂硅幏寰楅澶栧鍔卞垎鏁 if (last_step.player == PLAYER || last_step.player == PLAYER1) { - player1_final_score += WIN_BONUS; // 获胜奖励 + player1_final_score += WIN_BONUS; // 鑾疯儨濂栧姳 } else { - player2_final_score += WIN_BONUS; // 获胜奖励 + player2_final_score += WIN_BONUS; // 鑾疯儨濂栧姳 } } } - scores_calculated = 1; // 标记评分已计算 + scores_calculated = 1; // 鏍囪璇勫垎宸茶绠 } /** - * @brief 显示游戏评分结果和MVP评选 - * @param game_mode 游戏模式(1-人机对战, 2-双人对战) + * @brief 鏄剧ず娓告垙璇勫垎缁撴灉鍜孧VP璇勯 + * @param game_mode 娓告垙妯″紡(1-浜烘満瀵规垬, 2-鍙屼汉瀵规垬) */ void display_game_scores(int game_mode) { - printf("\n===== 对局评分 =====\n"); + printf("\n===== 瀵瑰眬璇勫垎 =====\n"); double sum_score = (long double)player1_final_score + (long double)player2_final_score; if (sum_score > 0) { if (game_mode == 1) { - printf("玩家得分: %d, 占比: %.2f%%\n", + printf("鐜╁寰楀垎: %d, 鍗犳瘮: %.2f%%\n", player1_final_score, (double)player1_final_score * 100.0 / sum_score); - printf("AI得分: %d, 占比: %.2f%%\n", + printf("AI寰楀垎: %d, 鍗犳瘮: %.2f%%\n", player2_final_score, (double)player2_final_score * 100.0 / sum_score); } else { - printf("玩家1(黑棋)得分: %d, 占比: %.2f%%\n", + printf("鐜╁1(榛戞)寰楀垎: %d, 鍗犳瘮: %.2f%%\n", player1_final_score, (double)player1_final_score * 100.0 / sum_score); - printf("玩家2(白棋)得分: %d, 占比: %.2f%%\n", + printf("鐜╁2(鐧芥)寰楀垎: %d, 鍗犳瘮: %.2f%%\n", player2_final_score, (double)player2_final_score * 100.0 / sum_score); } } @@ -241,41 +241,41 @@ void display_game_scores(int game_mode) { if (game_mode == 1) { - printf("玩家得分: %d\n", player1_final_score); - printf("AI得分: %d\n", player2_final_score); + printf("鐜╁寰楀垎: %d\n", player1_final_score); + printf("AI寰楀垎: %d\n", player2_final_score); } else { - printf("玩家1(黑棋)得分: %d\n", player1_final_score); - printf("玩家2(白棋)得分: %d\n", player2_final_score); + printf("鐜╁1(榛戞)寰楀垎: %d\n", player1_final_score); + printf("鐜╁2(鐧芥)寰楀垎: %d\n", player2_final_score); } - printf("注: 双方得分均为0,无法计算占比\n"); + printf("娉: 鍙屾柟寰楀垎鍧囦负0锛屾棤娉曡绠楀崰姣擻n"); } - // 评选MVP + // 璇勯塎VP if (player1_final_score > player2_final_score) { - printf("\nMVP: %s (领先 %d 分)\n", (game_mode == 1) ? "玩家" : "玩家1(黑棋)", player1_final_score - player2_final_score); + printf("\nMVP: %s (棰嗗厛 %d 鍒)\n", (game_mode == 1) ? "鐜╁" : "鐜╁1(榛戞)", player1_final_score - player2_final_score); } else if (player2_final_score > player1_final_score) { - printf("\nMVP: %s (领先 %d 分)\n", (game_mode == 1) ? "AI" : "玩家2(白棋)", player2_final_score - player1_final_score); + printf("\nMVP: %s (棰嗗厛 %d 鍒)\n", (game_mode == 1) ? "AI" : "鐜╁2(鐧芥)", player2_final_score - player1_final_score); } else { - printf("\n双方势均力敌!\n"); + printf("\n鍙屾柟鍔垮潎鍔涙晫锛乗n"); } } /** - * @brief 处理游戏结束后的记录保存 - * @return int 保存状态码(0-成功, 1-目录创建失败, 2-文件打开失败, 3-文件写入失败) + * @brief 澶勭悊娓告垙缁撴潫鍚庣殑璁板綍淇濆瓨 + * @return int 淇濆瓨鐘舵佺爜(0-鎴愬姛, 1-鐩綍鍒涘缓澶辫触, 2-鏂囦欢鎵撳紑澶辫触, 3-鏂囦欢鍐欏叆澶辫触) */ void handle_save_record(int game_mode) { int save_choice = 0; - printf("===== 游戏结束 =====\n"); - printf("是否保存游戏记录? (1-是, 0-否): "); + printf("===== 娓告垙缁撴潫 =====\n"); + printf("鏄惁淇濆瓨娓告垙璁板綍? (1-鏄, 0-鍚): "); scanf("%d", &save_choice); if (save_choice == 1) @@ -288,75 +288,75 @@ void handle_save_record(int game_mode) int save_status = save_game_to_file(filename, game_mode); switch (save_status) { - case 0: // 成功 - printf("\n游戏记录已成功保存至: %s (CSV格式)\n", filename); - printf("您可以使用以下命令进行复盘: .\\gobang.exe -l %s\n", filename); - printf("CSV格式文件可以直接用Excel打开查看和分析\n"); + case 0: // 鎴愬姛 + printf("\n娓告垙璁板綍宸叉垚鍔熶繚瀛樿嚦: %s (CSV鏍煎紡)\n", filename); + printf("鎮ㄥ彲浠ヤ娇鐢ㄤ互涓嬪懡浠よ繘琛屽鐩: .\\gobang.exe -l %s\n", filename); + printf("CSV鏍煎紡鏂囦欢鍙互鐩存帴鐢‥xcel鎵撳紑鏌ョ湅鍜屽垎鏋怽n"); break; - case 1: // 目录创建失败 - printf("\n游戏记录保存失败: 无法创建 'records' 目录。\n"); - printf("请检查程序是否具有足够的写入权限或磁盘空间是否充足。\n"); + case 1: // 鐩綍鍒涘缓澶辫触 + printf("\n娓告垙璁板綍淇濆瓨澶辫触: 鏃犳硶鍒涘缓 'records' 鐩綍銆俓n"); + printf("璇锋鏌ョ▼搴忔槸鍚﹀叿鏈夎冻澶熺殑鍐欏叆鏉冮檺鎴栫鐩樼┖闂存槸鍚﹀厖瓒炽俓n"); break; - case 2: // 文件打开失败 - printf("\n游戏记录保存失败: 无法在路径 '%s' 创建文件。\n", filename); - printf("请检查路径是否有效以及程序是否具有写入权限。\n"); + case 2: // 鏂囦欢鎵撳紑澶辫触 + printf("\n娓告垙璁板綍淇濆瓨澶辫触: 鏃犳硶鍦ㄨ矾寰 '%s' 鍒涘缓鏂囦欢銆俓n", filename); + printf("璇锋鏌ヨ矾寰勬槸鍚︽湁鏁堜互鍙婄▼搴忔槸鍚﹀叿鏈夊啓鍏ユ潈闄愩俓n"); break; - case 3: // 文件写入失败 - printf("\n游戏记录保存失败: 写入文件时发生错误。\n"); - printf("请检查磁盘空间是否已满。\n"); + case 3: // 鏂囦欢鍐欏叆澶辫触 + printf("\n娓告垙璁板綍淇濆瓨澶辫触: 鍐欏叆鏂囦欢鏃跺彂鐢熼敊璇俓n"); + printf("璇锋鏌ョ鐩樼┖闂存槸鍚﹀凡婊°俓n"); break; default: - printf("\n游戏记录保存失败: 发生未知错误。\n"); + printf("\n娓告垙璁板綍淇濆瓨澶辫触: 鍙戠敓鏈煡閿欒銆俓n"); break; } } } /** - * @brief 将当前游戏记录保存到文件 - * @param filename 要保存的文件名 - * @return int 错误码: - * 0: 成功 - * 1: 目录创建失败 - * 2: 文件打开失败 - * 3: 文件写入失败 + * @brief 灏嗗綋鍓嶆父鎴忚褰曚繚瀛樺埌鏂囦欢 + * @param filename 瑕佷繚瀛樼殑鏂囦欢鍚 + * @return int 閿欒鐮: + * 0: 鎴愬姛 + * 1: 鐩綍鍒涘缓澶辫触 + * 2: 鏂囦欢鎵撳紑澶辫触 + * 3: 鏂囦欢鍐欏叆澶辫触 */ int save_game_to_file(const char *filename, int game_mode) { - // 创建records目录(如果不存在) + // 鍒涘缓records鐩綍(濡傛灉涓嶅瓨鍦) struct stat st = {0}; if (stat("records", &st) == -1) { if (mkdir("records") != 0) { - // 检查是否目录已存在(多线程情况下可能被其他线程创建) + // 妫鏌ユ槸鍚︾洰褰曞凡瀛樺湪(澶氱嚎绋嬫儏鍐典笅鍙兘琚叾浠栫嚎绋嬪垱寤) if (stat("records", &st) == -1) { #ifdef _WIN32 - printf("错误:无法创建records目录\n"); - printf("可能原因:\n"); - printf("1. 没有写入权限 - 请尝试以管理员身份运行\n"); - printf("2. 防病毒软件阻止 - 请检查安全软件设置\n"); - printf("3. 路径无效 - 请检查工作目录\n"); + printf("閿欒锛氭棤娉曞垱寤簉ecords鐩綍\n"); + printf("鍙兘鍘熷洜锛歕n"); + printf("1. 娌℃湁鍐欏叆鏉冮檺 - 璇峰皾璇曚互绠$悊鍛樿韩浠借繍琛孿n"); + printf("2. 闃茬梾姣掕蒋浠堕樆姝 - 璇锋鏌ュ畨鍏ㄨ蒋浠惰缃甛n"); + printf("3. 璺緞鏃犳晥 - 璇锋鏌ュ伐浣滅洰褰昞n"); #else - perror("创建目录失败"); + perror("鍒涘缓鐩綍澶辫触"); #endif - return 1; // 目录创建失败 + return 1; // 鐩綍鍒涘缓澶辫触 } } } - // 打开文件 + // 鎵撳紑鏂囦欢 char fullpath[256]; snprintf(fullpath, sizeof(fullpath), "records/%s", filename); FILE *file = fopen(fullpath, "w"); if (!file) { - return 2; // 文件打开失败 + return 2; // 鏂囦欢鎵撳紑澶辫触 } - // 判断胜负结果 - strcpy(winner_info, "平局或未完成"); + // 鍒ゆ柇鑳滆礋缁撴灉 + strcpy(winner_info, "骞冲眬鎴栨湭瀹屾垚"); if (step_count > 0) { Step last_step = steps[step_count - 1]; @@ -364,72 +364,72 @@ int save_game_to_file(const char *filename, int game_mode) { if (game_mode == 1) { - // 人机对战 + // 浜烘満瀵规垬 if (last_step.player == PLAYER) { - strcpy(winner_info, "玩家获胜"); + strcpy(winner_info, "鐜╁鑾疯儨"); } else { - strcpy(winner_info, "AI获胜"); + strcpy(winner_info, "AI鑾疯儨"); } } else { - // 双人对战 + // 鍙屼汉瀵规垬 if (last_step.player == PLAYER1) { - strcpy(winner_info, "玩家1获胜"); + strcpy(winner_info, "鐜╁1鑾疯儨"); } else { - strcpy(winner_info, "玩家2获胜"); + strcpy(winner_info, "鐜╁2鑾疯儨"); } } } } - // 写入CSV文件头部 - if (fprintf(file, "游戏模式,棋盘大小,玩家1得分,玩家2得分,对局结果\n%d,%d,%d,%d,%s\n\n", game_mode, BOARD_SIZE, player1_final_score, player2_final_score, winner_info) < 0) + // 鍐欏叆CSV鏂囦欢澶撮儴 + if (fprintf(file, "娓告垙妯″紡,妫嬬洏澶у皬,鐜╁1寰楀垎,鐜╁2寰楀垎,瀵瑰眬缁撴灉\n%d,%d,%d,%d,%s\n\n", game_mode, BOARD_SIZE, player1_final_score, player2_final_score, winner_info) < 0) { fclose(file); - return 3; // 文件写入失败 + return 3; // 鏂囦欢鍐欏叆澶辫触 } - // 写入CSV表头 - if (fprintf(file, "步数,玩家,行坐标,列坐标\n") < 0) + // 鍐欏叆CSV琛ㄥご + if (fprintf(file, "姝ユ暟,鐜╁,琛屽潗鏍,鍒楀潗鏍嘰n") < 0) { fclose(file); - return 3; // 文件写入失败 + return 3; // 鏂囦欢鍐欏叆澶辫触 } - // 写入所有落子步骤(CSV格式) + // 鍐欏叆鎵鏈夎惤瀛愭楠わ紙CSV鏍煎紡锛 for (int i = 0; i < step_count; i++) { if (fprintf(file, "%d,%d,%d,%d\n", i+1, steps[i].player, steps[i].x+1, steps[i].y+1) < 0) { fclose(file); - return 3; // 文件写入失败 + return 3; // 鏂囦欢鍐欏叆澶辫触 } } if (fclose(file) != 0) { - return 3; // 文件关闭/写入失败 + return 3; // 鏂囦欢鍏抽棴/鍐欏叆澶辫触 } - return 0; // 成功 + return 0; // 鎴愬姛 } /** - * @brief 从文件加载游戏记录 - * @param filename 要加载的文件名 - * @return true 加载成功 - * @return false 加载失败 + * @brief 浠庢枃浠跺姞杞芥父鎴忚褰 + * @param filename 瑕佸姞杞界殑鏂囦欢鍚 + * @return true 鍔犺浇鎴愬姛 + * @return false 鍔犺浇澶辫触 */ int load_game_from_file(const char *filename) { - // 打开文件 + // 鎵撳紑鏂囦欢 char fullpath[256]; snprintf(fullpath, sizeof(fullpath), "records/%s", filename); FILE *file = fopen(fullpath, "r"); @@ -438,28 +438,28 @@ int load_game_from_file(const char *filename) return false; } - // 跳过CSV文件头部行 + // 璺宠繃CSV鏂囦欢澶撮儴琛 char buffer[256]; - if (fgets(buffer, sizeof(buffer), file) == NULL) // 跳过"游戏模式,棋盘大小" + if (fgets(buffer, sizeof(buffer), file) == NULL) // 璺宠繃"娓告垙妯″紡,妫嬬洏澶у皬" { fclose(file); return 0; } - // 读取游戏模式、棋盘大小和评分结果 + // 璇诲彇娓告垙妯″紡銆佹鐩樺ぇ灏忓拰璇勫垎缁撴灉 int game_mode, size; - // 尝试读取新格式(包含胜负信息) + // 灏濊瘯璇诲彇鏂版牸寮忥紙鍖呭惈鑳滆礋淇℃伅锛 int read_count = fscanf(file, "%d,%d,%d,%d,%49s", &game_mode, &size, &player1_final_score, &player2_final_score, winner_info); if (read_count == 4) { - // 旧格式文件,没有胜负信息 - strcpy(winner_info, "未知"); + // 鏃ф牸寮忔枃浠讹紝娌℃湁鑳滆礋淇℃伅 + strcpy(winner_info, "鏈煡"); } else if (read_count != 5) { - // 文件格式错误 + // 鏂囦欢鏍煎紡閿欒 fclose(file); return 0; } @@ -467,7 +467,7 @@ int load_game_from_file(const char *filename) if (game_mode != 1 && game_mode != 2) { fclose(file); - return 0; // 无效的游戏模式 + return 0; // 鏃犳晥鐨勬父鎴忔ā寮 } if (size < 5 || size > MAX_BOARD_SIZE) { @@ -475,24 +475,24 @@ int load_game_from_file(const char *filename) return false; } - // 设置评分已计算标志 + // 璁剧疆璇勫垎宸茶绠楁爣蹇 scores_calculated = 1; - // 跳过空行和表头行 - fgets(buffer, sizeof(buffer), file); // 跳过换行 - fgets(buffer, sizeof(buffer), file); // 跳过空行 - fgets(buffer, sizeof(buffer), file); // 跳过"步数,玩家,行坐标,列坐标" + // 璺宠繃绌鸿鍜岃〃澶磋 + fgets(buffer, sizeof(buffer), file); // 璺宠繃鎹㈣ + fgets(buffer, sizeof(buffer), file); // 璺宠繃绌鸿 + fgets(buffer, sizeof(buffer), file); // 璺宠繃"姝ユ暟,鐜╁,琛屽潗鏍,鍒楀潗鏍" - // 初始化棋盘 + // 鍒濆鍖栨鐩 BOARD_SIZE = size; empty_board(); - // 读取所有落子步骤 + // 璇诲彇鎵鏈夎惤瀛愭楠 step_count = 0; - int step_num; // 用于存储步数,但不使用 + int step_num; // 鐢ㄤ簬瀛樺偍姝ユ暟锛屼絾涓嶄娇鐢 while (fscanf(file, "%d,%d,%d,%d", &step_num, &steps[step_count].player, &steps[step_count].x, &steps[step_count].y) == 4) { - // 将1-based坐标转换为0-based坐标 + // 灏1-based鍧愭爣杞崲涓0-based鍧愭爣 steps[step_count].x--; steps[step_count].y--; step_count++; diff --git a/record.h b/record.h index c0f0c68..8b29a08 100644 --- a/record.h +++ b/record.h @@ -3,42 +3,42 @@ #include "gobang.h" -// --- 复盘与记录功能 --- +// --- 澶嶇洏涓庤褰曞姛鑳 --- /** - * @brief 进入复盘流程,回顾整局游戏 - * @param game_mode 游戏模式(1为人机对战,2为双人对战) + * @brief 杩涘叆澶嶇洏娴佺▼锛屽洖椤炬暣灞娓告垙 + * @param game_mode 娓告垙妯″紡锛1涓轰汉鏈哄鎴橈紝2涓哄弻浜哄鎴橈級 */ void review_process(int game_mode); /** - * @brief 将当前对局记录保存到文件 - * @param filename 要保存到的文件名 - * @param game_mode 游戏模式 - * @return 0表示成功,非0表示失败 + * @brief 灏嗗綋鍓嶅灞璁板綍淇濆瓨鍒版枃浠 + * @param filename 瑕佷繚瀛樺埌鐨勬枃浠跺悕 + * @param game_mode 娓告垙妯″紡 + * @return 0琛ㄧず鎴愬姛锛岄潪0琛ㄧず澶辫触 */ int save_game_to_file(const char *filename, int game_mode); /** - * @brief 处理保存游戏记录的逻辑 - * @param game_mode 游戏模式 + * @brief 澶勭悊淇濆瓨娓告垙璁板綍鐨勯昏緫 + * @param game_mode 娓告垙妯″紡 */ void handle_save_record(int game_mode); /** - * @brief 从文件加载游戏记录 - * @param filename 要加载的文件名 - * @return 游戏模式(1或2),0表示失败 + * @brief 浠庢枃浠跺姞杞芥父鎴忚褰 + * @param filename 瑕佸姞杞界殑鏂囦欢鍚 + * @return 娓告垙妯″紡锛1鎴2锛夛紝0琛ㄧず澶辫触 */ int load_game_from_file(const char *filename); /** - * @brief 计算游戏评分 + * @brief 璁$畻娓告垙璇勫垎 */ void calculate_game_scores(); /** - * @brief 显示游戏评分结果和MVP评选 - * @param game_mode 游戏模式(1-人机对战,2-双人对战) + * @brief 鏄剧ず娓告垙璇勫垎缁撴灉鍜孧VP璇勯 + * @param game_mode 娓告垙妯″紡锛1-浜烘満瀵规垬锛2-鍙屼汉瀵规垬锛 */ void display_game_scores(int game_mode); diff --git a/绠浠.txt b/绠浠.txt new file mode 100644 index 0000000..a0ebb23 --- /dev/null +++ b/绠浠.txt @@ -0,0 +1,76 @@ +/** + * @file 浜斿瓙妫嬪鎴樼郴缁 + * @brief C璇█浜斿瓙妫嬪妯″紡瀵规垬绯荤粺 + * @details 鏀寔浜烘満瀵规垬銆佸弻浜哄鎴樸佺綉缁滃鎴樼殑瀹屾暣浜斿瓙妫嬫父鎴忕郴缁 + * @author 鍒樿埅瀹(3364451258@qq.com銆15236416560@163.com銆乴hy3364451258@outlook.com) + * @date 2025-07-10 + * @version 6.0 + * @note + * 1. v6.0鏂板鍔熻兘锛 + * - 馃寪 瀹屾暣鐨勭綉缁滃鎴樻ā寮忥紝鏀寔鏈嶅姟鍣/瀹㈡埛绔灦鏋 + * - 馃敆 瀹炴椂鏁版嵁鍚屾锛屾敮鎸佽惤瀛愩佹倲妫嬨佽杈撱佽亰澶╃瓑缃戠粶鍔熻兘 + * - 馃洝锔 缃戠粶瀹夊叏楠岃瘉鍜岃繛鎺ョ姸鎬佺鐞 + * - 馃摗 璺ㄥ钩鍙扮綉缁滄敮鎸侊紙Windows/Linux锛 + * - 馃敡 鍏ㄥ眬鍙橀噺缁熶竴绠$悊锛屼紭鍖栦唬鐮佺粨鏋 + * - 馃搵 瀹忓畾涔夌粺涓绠$悊锛屾秷闄ら噸澶嶅畾涔 + * 2. 鏍稿績娓告垙鍔熻兘锛 + * - 澧炲姞浜嗗绂佹墜瑙勫垯鐨勬敮鎸侊紝闃叉鐜╁杩涜鏃犳剰涔夌殑璧版硶銆 + * - 鏂板浜嗘父鎴忚鏃跺櫒鍔熻兘锛岄檺鍒舵瘡鍥炲悎鐨勬濊冩椂闂淬 + * - 娣诲姞浜嗗鐩樺姛鑳斤紝鏀寔淇濆瓨鍜屽洖椤惧灞璁板綍銆 + * - 瀹炵幇浜嗚瘎鍒嗙郴缁燂紝鍙互瀵规瘡涓姝ユ杩涜璇勫垎鍜屽垎鏋愩 + * 3. 鎬ц兘浼樺寲锛 + * - 馃殌 浼樺寲浜咥I绠楁硶锛屼娇鐢ˋlpha-Beta鍓灊鎻愰珮鎼滅储鏁堢巼 + * - 馃帹 鏀硅繘浜嗘鐩樻覆鏌撶畻娉曪紝鍑忓皯浜嗕笉蹇呰鐨勯噸缁樻搷浣 + * - 馃捑 澧炲姞浜嗗唴瀛樼鐞嗕紭鍖栵紝閬垮厤鍐呭瓨娉勬紡闂 + * - 鈿 缃戠粶閫氫俊浼樺寲锛屾敮鎸佸紓姝ユ秷鎭鐞 + * - 馃攳 鏅鸿兘璇勫垎绠楁硶浼樺寲锛屾彁鍗嘇I鍐崇瓥璐ㄩ噺 + * 4. 鐢ㄦ埛鐣岄潰鏀硅繘锛 + * - 馃幃 缇庡寲浜嗘父鎴忕晫闈紝澧炲姞浜嗘洿澶氱殑瑙嗚鏁堟灉 + * - 鈱笍 鏀硅繘浜嗙敤鎴蜂氦浜掍綋楠岋紝澧炲姞浜嗗揩鎹烽敭鏀寔 + * - 馃攰 娣诲姞浜嗛煶鏁堝拰鑳屾櫙闊充箰锛屾彁鍗囨父鎴忔矇娴告劅 + * - 馃挰 缃戠粶瀵规垬鑱婂ぉ鐣岄潰锛屾敮鎸佸疄鏃朵氦娴 + * - 馃搳 娓告垙鐘舵佹樉绀轰紭鍖栵紝娓呮櫚灞曠ず杩炴帴鐘舵 + * 5. 浠g爜缁撴瀯浼樺寲锛 + * - 馃彈锔 閲嶆瀯浜嗕唬鐮佹灦鏋勶紝鎻愰珮浜嗕唬鐮佺殑鍙鎬у拰鍙淮鎶ゆ + * - 馃摑 澧炲姞浜嗚缁嗙殑娉ㄩ噴鍜屾枃妗o紝渚夸簬鐞嗚В鍜屼慨鏀 + * - 馃З 閲囩敤浜嗘ā鍧楀寲璁捐锛屽悇鍔熻兘妯″潡鐩稿鐙珛 + * - 馃實 鏂板缃戠粶妯″潡锛屽畬鏁寸殑缃戠粶閫氫俊鏋舵瀯 + * - 馃敡 鍏ㄥ眬鐘舵佺粺涓绠$悊锛屾秷闄や唬鐮侀噸澶 + * - 馃搵 閰嶇疆鏂囦欢鏍囧噯鍖栵紝鏀寔鐏垫椿閰嶇疆 + * 6. 寮傚父澶勭悊锛 + * - 馃洝锔 澧炲姞浜嗚緭鍏ラ敊璇殑寮傚父澶勭悊鏈哄埗锛岀‘淇濇父鎴忕殑绋冲畾鎬 + * - 馃挕 浼樺寲浜嗛敊璇彁绀轰俊鎭紝甯姪鐢ㄦ埛蹇熷畾浣嶉棶棰 + * - 馃攧 澧炲姞浜嗙▼搴忓穿婧冩仮澶嶅姛鑳斤紝鎻愰珮娓告垙鐨勫彲闈犳 + * - 馃寪 缃戠粶杩炴帴寮傚父澶勭悊锛岃嚜鍔ㄩ噸杩炲拰瓒呮椂绠$悊 + * - 馃摗 娑堟伅浼犺緭閿欒澶勭悊锛岀‘淇濇暟鎹畬鏁存 + * 7. 鏂囨。鏇存柊锛 + * - 馃摎 鏇存柊浜哛EADME鏂囦欢锛屾彁渚涜缁嗙殑瀹夎鍜屼娇鐢ㄨ鏄 + * - 馃挰 澧炲姞浜嗕唬鐮佹敞閲婏紝鎻愰珮浠g爜鐨勫彲璇绘 + * - 馃懆鈥嶐煉 娣诲姞浜嗗紑鍙戣呮枃妗o紝渚夸簬鍚庣画鐨勫姛鑳芥墿灞 + * - 馃寪 鏂板缃戠粶瀵规垬浣跨敤鎸囧崡鍜岄厤缃鏄 + * - 馃敡 API鏂囨。瀹屽杽锛屾敮鎸佷簩娆″紑鍙 + * 8. 鐗堟湰鎺у埗锛 + * - 馃摝 浣跨敤Git杩涜鐗堟湰鎺у埗锛屼究浜庝唬鐮佺鐞嗗拰鍗忎綔寮鍙 + * - 馃殌 寤虹珛浜嗘竻鏅扮殑鐗堟湰鍙戝竷娴佺▼锛岀‘淇濅唬鐮佽川閲 + * - 馃彿锔 v6.0閲嶅ぇ鐗堟湰鏇存柊锛岀綉缁滃姛鑳介噷绋嬬 + * - 馃搵 瀹屾暣鐨勫彉鏇存棩蹇楋紝杩借釜鍔熻兘婕旇繘 + * 9. 娴嬭瘯锛 + * - 鉁 杩涜浜嗗叏闈㈢殑鍔熻兘娴嬭瘯锛岀‘淇濆悇椤瑰姛鑳芥甯歌繍琛 + * - 馃И 澧炲姞浜嗗崟鍏冩祴璇曪紝鎻愰珮浠g爜鐨勫彲闈犳 + * - 鈿 杩涜浜嗘ц兘娴嬭瘯锛屼紭鍖栦簡绋嬪簭鐨勮繍琛屾晥鐜 + * - 馃寪 缃戠粶鍔熻兘鍘嬪姏娴嬭瘯锛岀‘淇濆浜哄鎴樼ǔ瀹氭 + * - 馃敀 瀹夊叏鎬ф祴璇曪紝楠岃瘉缃戠粶閫氫俊瀹夊叏 + * 10. 寮婧愬崗璁細 + * - 馃搫 閫夋嫨浜哅IT寮婧愬崗璁紝鍏佽鐢ㄦ埛鑷敱浣跨敤銆佷慨鏀瑰拰鍒嗗彂浠g爜 + * - 馃 娆㈣繋绀惧尯璐$尞锛屽叡鍚屽畬鍠勯」鐩 + * 11. 璐$尞鑰咃細 + * - 馃懆鈥嶐煉 鎰熻阿鎵鏈変负椤圭洰鍋氬嚭璐$尞鐨勫紑鍙戣呭拰鐢ㄦ埛 + * - 馃専 鐗瑰埆鎰熻阿缃戠粶鍔熻兘寮鍙戝拰娴嬭瘯鐨勮础鐚 + * 12. 鑱旂郴淇℃伅锛 + * - 馃摟 濡傛湁闂鎴栧缓璁紝璇疯仈绯诲紑鍙戣咃細 + * - 3364451258@qq.com + * - 15236416560@163.com + * - lhy3364451258@outlook.com + * - 馃悰 Bug鎶ュ憡鍜屽姛鑳藉缓璁杩庨氳繃閭欢鍙嶉 + * - 馃挕 缃戠粶瀵规垬鐩稿叧闂璇疯缁嗘弿杩扮綉缁滅幆澧 + */ \ No newline at end of file