#include "ai.h" #include #include #include extern int BOARD_SIZE; extern int board[MAX_BOARD_SIZE][MAX_BOARD_SIZE]; extern int step_count; extern const int direction[4][2]; extern Step steps[MAX_STEPS]; /** * @brief ????????????????????????? * ?????????????????????????????????????????????????? * ???????????????????????????????? * @param x ????????????? (0-based)?? * @param y ????????????? (0-based)?? * @param player ????? (PLAYER ?? AI)?????????????????????? * @return int ??????????????????????? * @note ?????????? * - ??????????????????????M??????????????????????????? * - ?????????????????\????????????????????\????????????????????\????????? * ????????????????????? * - ?????? (??????????????????AI???): * - ????: 1,000,000 (???) * - ????: 100,000 (????????) * - ????: 10,000 (????????????) * - ????: 5,000 (??????) * - ????: 1,000 * - ???: 500 * - ???: 100 * - ????: ???????? * - ?????????????????????????????????????????????????????????AI???????? */ 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}; // ??????????? // ?????????????????? 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 1000000; // ???????? } // ?????????????????? switch (info.continuous_chess) { case 4: // ?????? if (info.check_start && info.check_end) // ????(???????) line_scores[i] = 100000; else if (info.check_start || info.check_end) // ????(??????) line_scores[i] = 10000; else // ????(??????) line_scores[i] = 500; break; case 3: // ?????? if (info.check_start && info.check_end) // ???? line_scores[i] = 5000; else if (info.check_start || info.check_end) // ???? line_scores[i] = 1000; else // ???? line_scores[i] = 50; break; case 2: // ?????? if (info.check_start && info.check_end) // ??? line_scores[i] = 500; else if (info.check_start || info.check_end) // ??? line_scores[i] = 100; else // ???? line_scores[i] = 10; break; case 1: // ???? if (info.check_start && info.check_end) // ???????? line_scores[i] = 50; else if (info.check_start || info.check_end) // ???????? line_scores[i] = 10; else // ??????? line_scores[i] = 1; break; } } // ???????????????+????????????? int max_score = 0; int sum_score = 0; for (int i = 0; i < 4; i++) { if (line_scores[i] > max_score) max_score = line_scores[i]; sum_score += line_scores[i]; } 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 = 50 * (BOARD_SIZE - distance); // ?????????????????? board[x][y] = original; // ????????? return total_score + position_bonus; // ???????????? } /** * @brief ??????-???????????????????Minimax????????????????? * ?????????????????????????????????????????????????????? * @param x ???????????????? * @param y ???????????????? * @param player ??????????? (PLAYER ?? AI)?? * @param depth ??????????????????AI???????????????????? * @param alpha ?????????????AI????????????????????????? * @param beta ??????????????????????????????????????????? * @param is_maximizing ???????true???????????????AI???????false???????????????????????? * @return int ??????????????????????????? * @note ?????????: * 1. **??????????**: ????????????????????????????????????????????????????????????????? * 2. **??????? (AI)**: ??????????????????????????????????????????????????????????alpha??? * 3. **????????? (????)**: ????????????????????????????AI???????????????????????????????????beta??? * 4. **??-????**: ?????Minimax??????????? * - **?????**: ????????????????????????????????????????alpha????????????????????????? * ??????????????????????????????????????????(if beta <= alpha) * - **????**: ??????????ah?????????????????????????????beta?????????????????????????? * ???????????????????????????????????????????????????????(if beta <= alpha) * ????????????????????????????????????????????AI?????????? */ int dfs(int x, int y, int player, int depth, int alpha, int beta, bool is_maximizing) { // ???n?????????? if (check_win(x, y, player)) { return (player == AI) ? 1000000 + depth : -1000000 - depth; } // ????????????? if (depth == 0 || step_count >= BOARD_SIZE * BOARD_SIZE) { return evaluate_pos(x, y, AI) - evaluate_pos(x, y, PLAYER); } int best_score = is_maximizing ? -1000000 : 1000000; // ???????????????????? for (int i = 0; i < BOARD_SIZE; i++) { for (int j = 0; j < BOARD_SIZE; j++) { if (board[i][j] != EMPTY) 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)??? 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; } } } if ((is_maximizing && best_score >= beta) || (!is_maximizing && best_score <= alpha)) { break; // ???????????? } } return best_score; } /** * @brief AI????????????????????????????????????????????? * @note ?????????????????? * 1. ???????????????????????????????????????????????? * 2. ???????????????????????????DFS????????????????? * @note ??????? * - ?????????????????????????? * - ????>10??????????????????????????2?? * - ?????????????????? */ void ai_move(int depth) { // 1. ??????????????????????????????????? for (int i = 0; i < BOARD_SIZE; i++) { for (int j = 0; j < BOARD_SIZE; j++) { if (board[i][j] != EMPTY) 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; break; } } 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); return; } } } // 2. ????????????????????????????????? int best_score = -1000000; int best_x = -1, best_y = -1; // ???????????????? for (int i = 0; i < BOARD_SIZE; i++) { for (int j = 0; j < BOARD_SIZE; j++) { if (board[i][j] != EMPTY) continue; // ????????????????(2??????) bool has_nearby_stone = false; for (int di = -2; di <= 2; di++) { for (int dj = -2; dj <= 2; dj++) { int ni = i + di; int nj = j + dj; if (ni >= 0 && ni < BOARD_SIZE && nj >= 0 && nj < BOARD_SIZE) { if (board[ni][nj] != EMPTY) { has_nearby_stone = true; break; } } } if (has_nearby_stone) break; } if (!has_nearby_stone && step_count > 10) continue; // ???AI???? board[i][j] = AI; int current_score = dfs(i, j, PLAYER, depth, -1000000, 1000000, false); board[i][j] = EMPTY; // ??????????? if (current_score > best_score) { best_score = current_score; best_x = i; best_y = j; } } } // ?????????? 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); } }