#include   <graphics.
h>
#include   <conio.h>
#include   <math.h>
#include   <stdlib.h>
#include   <string.h>
#include   <time.h>
#include   <windows.h>
#include   <stdio.h>
#define BOARD_SIZE 20
#define CELL_SIZE 18
int   ChessMap[BOARD_SIZE][BOARD_SIZE] = { 0 }; // 0: 空;1: 黑;2: 白(AI)
int   flag = 0;               // 0: 玩家回合;1: AI 回合
int   game_status = 0;        // 0: 进行中;1: 玩家胜;2: AI 胜;3: 平局
int   difficulty = -1;        // AI 难度,-1 表示未选择
// 初始化游戏界面
void initGame() {
    initgraph(500, 360, SHOWCONSOLE);
      IMAGE img;
      loadimage(&img, "bk.jpg");
      putimage(0, 0, &img);
      setlinecolor(BLACK);
      for (int i = 0; i <= BOARD_SIZE; i++) {
          line(0, i * CELL_SIZE, 360, i * CELL_SIZE);
          line(i * CELL_SIZE, 0, i * CELL_SIZE, 360);
      }
      setbkmode(TRANSPARENT);
      settextcolor(WHITE);
      outtextxy(380, 50, "玩家:黑棋");
      outtextxy(380, 80, "AI :白棋");
}
// 判断胜利函数
int judge(int row, int col) {
    int color = ChessMap[row][col];
    if (color == 0) return 0;
      // 横向检查
      int count = 1;
      for (int i = col + 1; i < BOARD_SIZE && ChessMap[row][i] == color; i++) {
          count++;
      }
      for (int i = col - 1; i >= 0 && ChessMap[row][i] == color; i--) {
          count++;
      }
      if (count >= 5) return color;
      // 纵向检查
      count = 1;
      for (int i = row + 1; i < BOARD_SIZE && ChessMap[i][col] == color; i++) {
          count++;
      }
      for (int i = row - 1; i >= 0 && ChessMap[i][col] == color; i--) {
          count++;
    }
    if (count >= 5) return color;
    // 左上 - 右下斜向检查
    count = 1;
    for (int i = 1; row + i < BOARD_SIZE && col + i < BOARD_SIZE && ChessMap[row +
i][col + i] == color; i++) {
        count++;
    }
    for (int i = 1; row - i >= 0 && col - i >= 0 && ChessMap[row - i][col - i] ==
color; i++) {
        count++;
    }
    if (count >= 5) return color;
    // 右上 - 左下斜向检查
    count = 1;
    for (int i = 1; row - i >= 0 && col + i < BOARD_SIZE && ChessMap[row - i][col +
i] == color; i++) {
        count++;
    }
    for (int i = 1; row + i < BOARD_SIZE && col - i >= 0 && ChessMap[row + i][col -
i] == color; i++) {
        count++;
    }
    if (count >= 5) return color;
    return 0;
}
// 评估某个位置的得分
int evaluate(int row, int col, int color) {
    int score = 0;
    int directions[4][2] = { {1, 0}, {0, 1}, {1, 1}, {1, -1} };
    for (int d = 0; d < 4; d++) {
        int dx = directions[d][0];
        int dy = directions[d][1];
        int count = 1;
        int emptyCountLeft = 0;
        int emptyCountRight = 0;
        // 正向检查
        for (int i = 1; row + i * dy < BOARD_SIZE && col + i * dx < BOARD_SIZE &&
col + i * dx >= 0; i++) {
            if (ChessMap[row + i * dy][col + i * dx] == color) {
                count++;
            }
            else if (ChessMap[row + i * dy][col + i * dx] == 0) {
                emptyCountRight++;
                break;
            }
            else {
                break;
            }
        }
        // 反向检查
        for (int i = 1; row - i * dy >= 0 && col - i * dx < BOARD_SIZE && col - i *
dx >= 0; i++) {
            if (ChessMap[row - i * dy][col - i * dx] == color) {
                count++;
            }
            else if (ChessMap[row - i * dy][col - i * dx] == 0) {
                emptyCountLeft++;
                break;
            }
            else {
                break;
            }
        }
        // 根据连子数量和空位情况计算得分
        if (count >= 5) {
            score += 10000;
        }
        else if (count == 4) {
            if (emptyCountLeft + emptyCountRight >= 1) {
                score += 1000;
            }
        }
        else if (count == 3) {
            if (emptyCountLeft + emptyCountRight >= 2) {
                score += 100;
            }
        }
        else if (count == 2) {
            if (emptyCountLeft + emptyCountRight >= 3) {
                score += 10;
            }
        }
    }
    return score;
}
// AI 落子函数
void AI_Move(int difficulty, int* lastX, int* lastY) {
    int x = 0, y = 0;
    switch (difficulty) {
    case 0: // 简单模式:随机落子
        do {
             x = rand() % BOARD_SIZE;
             y = rand() % BOARD_SIZE;
        } while (ChessMap[x][y] != 0);
        break;
    case 1: { // 中等模式:优先靠近现有棋子
        int move_found = 0;
        for (int dx = -1; dx <= 1 && !move_found; dx++) {
            for (int dy = -1; dy <= 1 && !move_found; dy++) {
                if (dx == 0 && dy == 0) continue;
                for (int i = 1; i < 5; i++) {
                    int cx = 9 + dx * i;
                    int cy = 9 + dy * i;
                    if (cx < 0 || cx >= BOARD_SIZE || cy < 0 || cy >= BOARD_SIZE)
continue;
                     if (ChessMap[cx][cy] == 0) {
                         for (int ddx = -1; ddx <= 1; ddx++) {
                             for (int ddy = -1; ddy <= 1; ddy++) {
                                 if (ddx == 0 && ddy == 0) continue;
                                 int nx = cx + ddx;
                                 int ny = cy + ddy;
                                 if (nx >= 0 && nx < BOARD_SIZE && ny >= 0 && ny <
BOARD_SIZE && ChessMap[nx][ny] == 2) {
                                     x = cx;
                                     y = cy;
                                     move_found = 1;
                                     break;
                                 }
                             }
                             if (move_found) break;
                         }
                     }
                 }
            }
        }
        if (!move_found) {
            do {
                 x = rand() % BOARD_SIZE;
                 y = rand() % BOARD_SIZE;
            } while (ChessMap[x][y] != 0);
        }
        break;
    }
    case 2: { // 困难模式:优先堵截玩家连子或创造自己连子,考虑潜在连子
        int best_score = -1;
        int best_move_x = -1, best_move_y = -1;
        for (int i = 0; i < BOARD_SIZE; i++) {
            for (int j = 0; j < BOARD_SIZE; j++) {
                if (ChessMap[i][j] == 0) {
                    // 评估自己落子的得分
                    ChessMap[i][j] = 2;
                    int score_self = evaluate(i, j, 2);
                    ChessMap[i][j] = 0;
                    // 评估阻止玩家落子的得分
                    ChessMap[i][j] = 1;
                    int score_opponent = evaluate(i, j, 1);
                    ChessMap[i][j] = 0;
                    int total_score = score_self * 2 + score_opponent; // 自己落子得分权重更
高
                    if (total_score > best_score) {
                        best_score = total_score;
                        best_move_x = i;
                        best_move_y = j;
                    }
                }
            }
        }
        x = best_move_x;
    y = best_move_y;
    break;
}
case 3: { // 地狱模式:考虑更长远的局势,更注重创造自己的连子和阻止玩家的连子
    int best_score = -1;
    int best_move_x = -1, best_move_y = -1;
    for (int i = 0; i < BOARD_SIZE; i++) {
        for (int j = 0; j < BOARD_SIZE; j++) {
            if (ChessMap[i][j] == 0) {
                // 评估自己落子的得分
                ChessMap[i][j] = 2;
                int score_self = evaluate(i, j, 2);
                  // 评估阻止玩家落子的得分
                  ChessMap[i][j] = 1;
                  int score_opponent = evaluate(i, j, 1);
                  ChessMap[i][j] = 0;
                  // 考虑更长远的局势,增加对自己连子的权重
                  int total_score = score_self * 3 + score_opponent * 2;
                  if (total_score > best_score) {
                      best_score = total_score;
                      best_move_x = i;
                      best_move_y = j;
                  }
              }
        }
    }
    x = best_move_x;
    y = best_move_y;
    break;
}
}
ChessMap[x][y] = 2;
setfillcolor(WHITE);
// 绘制棋子到格子中心
solidcircle(y * CELL_SIZE + CELL_SIZE / 2, x * CELL_SIZE + CELL_SIZE / 2, 7);
// 记录当前落子位置
*lastX = x;
*lastY = y;
// 保存数据到文件
FILE* fp = fopen("data.txt", "a");
if (fp != NULL) {
    fprintf(fp, "AI Move: Row %d, Col %d\n", x, y);
    for (int i = 0; i < BOARD_SIZE; i++) {
        for (int j = 0; j < BOARD_SIZE; j++) {
            fprintf(fp, "%d ", ChessMap[i][j]);
        }
        fprintf(fp, "\n");
    }
    fclose(fp);
}
}
// 优化鼠标点击处理,确保落在格子中心附近
void handleMouseClick(MOUSEMSG msg) {
    if (msg.uMsg == WM_LBUTTONDOWN) {
        // 检查点击位置是否在棋盘范围内
        if (msg.x >= 0 && msg.x < 360 && msg.y >= 0 && msg.y < 360) {
            int centerX = (msg.x / CELL_SIZE) * CELL_SIZE + CELL_SIZE / 2;
            int centerY = (msg.y / CELL_SIZE) * CELL_SIZE + CELL_SIZE / 2;
            int dx = msg.x - centerX;
            int dy = msg.y - centerY;
            // 判断是否点击在格子中心附近
            if (dx * dx + dy * dy <= (CELL_SIZE / 2) * (CELL_SIZE / 2)) {
                int col = msg.x / CELL_SIZE;
                int row = msg.y / CELL_SIZE;
                if (col < 0 || col >= BOARD_SIZE || row < 0 || row >= BOARD_SIZE ||
ChessMap[row][col] != 0) return;
                ChessMap[row][col] = 1;
                setfillcolor(BLACK);
                // 绘制棋子到格子中心
                solidcircle(col * CELL_SIZE + CELL_SIZE / 2, row * CELL_SIZE +
CELL_SIZE / 2, 7);
                // 保存数据到文件
                FILE* fp = fopen("data.txt", "a");
                if (fp != NULL) {
                    fprintf(fp, "Player Move: Row %d, Col %d\n", row, col);
                    for (int i = 0; i < BOARD_SIZE; i++) {
                        for (int j = 0; j < BOARD_SIZE; j++) {
                            fprintf(fp, "%d ", ChessMap[i][j]);
                        }
                        fprintf(fp, "\n");
                    }
                    fclose(fp);
                }
                // 只判断当前落子位置是否获胜
                if (judge(row, col) == 1) {
                    HWND hwnd = GetHWnd();
                    MessageBox(hwnd, "玩家胜利!", "游戏结束", MB_OK);
                    closegraph();
                    exit(0);
                }
                flag++;
            }
        }
    }
}
int main() {
    srand((unsigned)time(NULL));
    initGame();
    HWND hwnd = GetHWnd();
    while (difficulty == -1) {
        printf("选择 AI 难度(简单:0 中等:1 困难:2 地狱:3):");
        scanf("%d", &difficulty);
        if (difficulty < 0 || difficulty > 3) {
            MessageBox(hwnd, "无效难度!", "提示", MB_OK);
            difficulty = -1;
        }
    }
    // 提示选择好难度
    printf("你已经选择好相应难度!\n");
    // 保存初始难度信息到文件
    FILE* fp = fopen("data.txt", "w");
    if (fp != NULL) {
        fprintf(fp, "AI Difficulty: %d\n", difficulty);
        fclose(fp);
    }
    int lastX = -1, lastY = -1;
    while (1) {
        if (flag % 2 == 0) { // 玩家回合
            MOUSEMSG msg = GetMouseMsg();
            handleMouseClick(msg);
        }
        else { // AI 回合
            AI_Move(difficulty, &lastX, &lastY);
            flag++;
            // 只判断当前 AI 落子位置是否获胜
            if (lastX != -1 && lastY != -1) {
                int win = judge(lastX, lastY);
                if (win == 2) {
                    MessageBox(hwnd, "AI 胜利!", "游戏结束", MB_OK);
                    closegraph();
                    return 0;
                }
            }
        }
        // 检查平局
        int is_full = 1;
        for (int i = 0; i < BOARD_SIZE; i++) {
            for (int j = 0; j < BOARD_SIZE; j++) {
                if (ChessMap[i][j] == 0) {
                    is_full = 0;
                    break;
                }
            }
            if (!is_full) break;
        }
        if (is_full) {
            MessageBox(hwnd, "平局!", "游戏结束", MB_OK);
            closegraph();
            return 0;
        }
    }
    closegraph();
    return 0;
}