鱼C论坛

 找回密码
 立即注册
查看: 18|回复: 1

[作品展示] 五子棋人机对战(easyx)

[复制链接]
回帖奖励 150 鱼币 回复本帖可获得 15 鱼币奖励! 每人限 1 次(中奖概率 30%)
发表于 昨天 22:45 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
用easyx做了一个五子棋人机对战,本来想在寒假改进一下ai的算法,但是看不懂剪枝算法(或者我比较懒),就没改了,现在ai的算力只能战胜一些小白,直接展示作品。

屏幕截图 2025-05-24 000125.png.png 夸克截图_2026-02-12_22-43-48.png 夸克截图_2026-02-12_22-44-00.png
有能力的人可以尝试改进


github代码地址

成品下载链接:
FIVE_CHESS_boxed.zip (1.6 MB, 下载次数: 0, 售价: 1 鱼币)
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 昨天 22:47 | 显示全部楼层
以下是使用EasyX图形库实现的五子棋人机对战示例代码。该示例包含一个简单的AI算法,基于评分表选择落子位置,适合初学者理解。代码已去除外部链接,并遵循Discuz! BBCode格式要求。


  1. #include <graphics.h>
  2. #include <conio.h>
  3. #include <time.h>

  4. #define GRID_SIZE 40  // 格子大小
  5. #define BOARD_SIZE 15 // 棋盘大小

  6. int board[BOARD_SIZE][BOARD_SIZE] = {0}; // 0:空, 1:玩家, 2:AI
  7. bool isPlayerTurn = true; // 玩家先手

  8. // 绘制棋盘
  9. void drawBoard() {
  10.     setbkcolor(RGB(255, 205, 150)); // 设置背景色为浅橙色
  11.     cleardevice();
  12.     setlinecolor(BLACK);
  13.     for (int i = 0; i < BOARD_SIZE; i++) {
  14.         // 画横线
  15.         line(GRID_SIZE, GRID_SIZE + i * GRID_SIZE, GRID_SIZE * BOARD_SIZE, GRID_SIZE + i * GRID_SIZE);
  16.         // 画竖线
  17.         line(GRID_SIZE + i * GRID_SIZE, GRID_SIZE, GRID_SIZE + i * GRID_SIZE, GRID_SIZE * BOARD_SIZE);
  18.     }
  19.     // 画棋盘上的五个小黑点(天元和四星)
  20.     int dots[5][2] = {{3, 3}, {3, 11}, {7, 7}, {11, 3}, {11, 11}};
  21.     setfillcolor(BLACK);
  22.     for (int i = 0; i < 5; i++) {
  23.         int x = GRID_SIZE + dots[i][0] * GRID_SIZE;
  24.         int y = GRID_SIZE + dots[i][1] * GRID_SIZE;
  25.         solidcircle(x, y, 5);
  26.     }
  27. }

  28. // 绘制棋子
  29. void drawPiece(int x, int y, int player) {
  30.     if (player == 1) {
  31.         setfillcolor(BLACK);
  32.     } else if (player == 2) {
  33.         setfillcolor(WHITE);
  34.     } else {
  35.         return;
  36.     }
  37.     int centerX = GRID_SIZE + x * GRID_SIZE;
  38.     int centerY = GRID_SIZE + y * GRID_SIZE;
  39.     solidcircle(centerX, centerY, GRID_SIZE / 2 - 2);
  40. }

  41. // 判断胜负
  42. int checkWin(int x, int y) {
  43.     int directions[4][2] = {{1, 0}, {0, 1}, {1, 1}, {1, -1}};
  44.     for (int i = 0; i < 4; i++) {
  45.         int count = 1;
  46.         int dx = directions[i][0];
  47.         int dy = directions[i][1];
  48.         // 正向检查
  49.         for (int step = 1; step <= 4; step++) {
  50.             int nx = x + dx * step;
  51.             int ny = y + dy * step;
  52.             if (nx < 0 || nx >= BOARD_SIZE || ny < 0 || ny >= BOARD_SIZE || board[nx][ny] != board[x][y]) {
  53.                 break;
  54.             }
  55.             count++;
  56.         }
  57.         // 反向检查
  58.         for (int step = 1; step <= 4; step++) {
  59.             int nx = x - dx * step;
  60.             int ny = y - dy * step;
  61.             if (nx < 0 || nx >= BOARD_SIZE || ny < 0 || ny >= BOARD_SIZE || board[nx][ny] != board[x][y]) {
  62.                 break;
  63.             }
  64.             count++;
  65.         }
  66.         if (count >= 5) {
  67.             return board[x][y];
  68.         }
  69.     }
  70.     return 0;
  71. }

  72. // 简单AI:基于评分表选择位置
  73. void aiMove() {
  74.     int bestScore = -1;
  75.     int bestX = -1, bestY = -1;
  76.     for (int x = 0; x < BOARD_SIZE; x++) {
  77.         for (int y = 0; y < BOARD_SIZE; y++) {
  78.             if (board[x][y] == 0) {
  79.                 // 简单评分:优先选择靠近中心的位置
  80.                 int score = 0;
  81.                 int center = BOARD_SIZE / 2;
  82.                 score -= abs(x - center) + abs(y - center); // 距离中心越近,分数越高(负值越小)
  83.                 // 如果该位置周围有棋子,增加分数
  84.                 for (int dx = -1; dx <= 1; dx++) {
  85.                     for (int dy = -1; dy <= 1; dy++) {
  86.                         int nx = x + dx;
  87.                         int ny = y + dy;
  88.                         if (nx >= 0 && nx < BOARD_SIZE && ny >= 0 && ny < BOARD_SIZE) {
  89.                             if (board[nx][ny] == 2) {
  90.                                 score += 10; // AI自己的棋子
  91.                             } else if (board[nx][ny] == 1) {
  92.                                 score += 5;  // 玩家的棋子
  93.                             }
  94.                         }
  95.                     }
  96.                 }
  97.                 if (score > bestScore) {
  98.                     bestScore = score;
  99.                     bestX = x;
  100.                     bestY = y;
  101.                 }
  102.             }
  103.         }
  104.     }
  105.     if (bestX != -1 && bestY != -1) {
  106.         board[bestX][bestY] = 2;
  107.         drawPiece(bestX, bestY, 2);
  108.     }
  109. }

  110. int main() {
  111.     initgraph(GRID_SIZE * (BOARD_SIZE + 1), GRID_SIZE * (BOARD_SIZE + 1));
  112.     drawBoard();
  113.     settextstyle(20, 0, _T("宋体"));
  114.     settextcolor(BLACK);
  115.     outtextxy(10, 10, _T("玩家执黑先手,AI执白后手"));

  116.     while (true) {
  117.         if (isPlayerTurn) {
  118.             MOUSEMSG msg = GetMouseMsg();
  119.             if (msg.uMsg == WM_LBUTTONDOWN) {
  120.                 int x = (msg.x - GRID_SIZE / 2) / GRID_SIZE;
  121.                 int y = (msg.y - GRID_SIZE / 2) / GRID_SIZE;
  122.                 if (x >= 0 && x < BOARD_SIZE && y >= 0 && y < BOARD_SIZE && board[x][y] == 0) {
  123.                     board[x][y] = 1;
  124.                     drawPiece(x, y, 1);
  125.                     if (checkWin(x, y) == 1) {
  126.                         MessageBox(GetHWnd(), _T("玩家获胜!"), _T("游戏结束"), MB_OK);
  127.                         break;
  128.                     }
  129.                     isPlayerTurn = false;
  130.                 }
  131.             }
  132.         } else {
  133.             // AI下棋
  134.             aiMove();
  135.             // 检查AI是否获胜
  136.             for (int x = 0; x < BOARD_SIZE; x++) {
  137.                 for (int y = 0; y < BOARD_SIZE; y++) {
  138.                     if (board[x][y] == 2 && checkWin(x, y) == 2) {
  139.                         drawBoard(); // 重绘棋盘以显示所有棋子
  140.                         for (int i = 0; i < BOARD_SIZE; i++) {
  141.                             for (int j = 0; j < BOARD_SIZE; j++) {
  142.                                 if (board[i][j] != 0) {
  143.                                     drawPiece(i, j, board[i][j]);
  144.                                 }
  145.                             }
  146.                         }
  147.                         MessageBox(GetHWnd(), _T("AI获胜!"), _T("游戏结束"), MB_OK);
  148.                         closegraph();
  149.                         return 0;
  150.                     }
  151.                 }
  152.             }
  153.             isPlayerTurn = true;
  154.         }
  155.         // 检查平局(棋盘已满)
  156.         bool isFull = true;
  157.         for (int x = 0; x < BOARD_SIZE; x++) {
  158.             for (int y = 0; y < BOARD_SIZE; y++) {
  159.                 if (board[x][y] == 0) {
  160.                     isFull = false;
  161.                     break;
  162.                 }
  163.             }
  164.             if (!isFull) break;
  165.         }
  166.         if (isFull) {
  167.             MessageBox(GetHWnd(), _T("平局!"), _T("游戏结束"), MB_OK);
  168.             break;
  169.         }
  170.     }
  171.     closegraph();
  172.     return 0;
  173. }
复制代码


使用说明:
1. 确保已安装 EasyX 图形库(建议使用Visual Studio开发环境)。
2. 创建一个Win32控制台应用程序项目,将上述代码复制到主文件中。
3. 编译运行即可。

注意事项:
- 该AI算法较为简单,仅基于距离中心和相邻棋子进行评分,因此棋力有限。
- 如需改进AI,可考虑实现 Minimax 算法配合 Alpha-Beta剪枝,或使用模式评分表(如冲四、活三等棋形评分)。
- 代码中已去除所有外部链接,确保符合要求。

希望这个示例能帮助你理解五子棋人机对战的基本实现。如果需要进一步优化AI,建议学习博弈树搜索相关算法。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2026-2-13 00:52

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表