Files
C_code/课上代码练习/五子棋/README.md
T

9.8 KiB
Raw Blame History

五子棋人机对战AI项目

项目简介

这是一个基于C语言实现的高级五子棋人机对战系统,采用α-β剪枝的极小极大算法实现AI决策,支持自定义棋盘大小和完整的游戏复盘功能。

核心功能

  • 支持5x5到25x25的棋盘尺寸
  • 玩家(X)与AI(○)对战模式
  • AI采用α-β剪枝优化的极小极大算法
  • 详细的棋型评估系统(活四、冲四、活三等)
  • 完整的游戏复盘功能
  • 清晰的棋盘界面显示

技术特点

  1. AI算法

    • 使用α-β剪枝优化的极小极大算法
    • 搜索深度可调(当前设置为3层)
    • 优先处理威胁位置(如阻止玩家形成活四)
  2. 评估系统

    • 考虑四个方向的棋型评估
    • 区分活棋、眠棋和死棋
    • 位置奖励(中心位置价值更高)
  3. 游戏流程

    • 完整的胜负判定
    • 平局检测
    • 详细的复盘系统

编译运行

  1. 编译程序:

    gcc "C语言代码/课上代码练习/五子棋/五子棋 copy 3.c" -o gomoku -lm
    
  2. 运行游戏:

    ./gomoku
    

使用说明

  1. 启动后输入棋盘尺寸(5-25,默认15)
  2. 游戏进行:
    • 玩家输入坐标格式:行 列(如"8 8"
    • AI会自动计算最佳落子位置
  3. 游戏结束:
    • 显示胜负结果
    • 可选择查看完整复盘

核心函数说明

1. ai_move() - AI决策函数

功能:决定AI的最佳落子位置
算法

  1. 优先检查是否需要阻止玩家形成活四/冲四
  2. 使用α-β剪枝优化的极小极大算法搜索最佳位置
  3. 考虑已有棋子附近2格范围内的位置

参数:无
返回值:无(直接修改棋盘状态)

2. evaluate_pos() - 棋型评估函数

功能:评估特定位置对当前玩家的价值
评分标准

  • 活四: 100000分
  • 冲四: 10000分
  • 活三: 5000分
  • 眠三: 1000分
  • 活二: 500分
  • 眠二: 100分

参数

  • x,y: 待评估位置坐标
  • player: 当前玩家标识 返回值:评估分数(越高越好)

3. dfs() - 深度优先搜索

功能:实现带α-β剪枝的极小极大算法
特点

  • 搜索深度:3层
  • 使用α-β剪枝优化搜索效率
  • 评估函数差值作为叶节点值 参数
  • x,y: 当前落子位置
  • player: 当前玩家
  • depth: 剩余搜索深度
  • alpha,beta: 剪枝参数
  • is_maximizing: 是否最大化玩家

4. count_specific_direction() - 方向分析

功能:计算特定方向上的连续棋子情况
返回结构

  • continuous_chess: 连续棋子数
  • check_start/check_end: 两端是否开放 应用:用于判断棋型(活棋/眠棋)

5. check_win() - 胜负判断

功能:检查落子后是否形成五连珠
逻辑:检查四个方向是否存在≥5的连续同色棋子

程序流程图

开始
│
├─> 初始化棋盘
│    │
│    └─> 设置默认大小(15x15)
│
├─> 游戏主循环
│    │
│    ├─> [玩家回合]
│    │    ├─> 显示棋盘
│    │    ├─> 获取玩家输入坐标
│    │    └─> 落子并检查胜负
│    │
│    ├─> [AI回合]
│    │    ├─> AI计算最佳落子(α-β剪枝)
│    │    └─> 落子并检查胜负
│    │
│    └─> 检查平局条件
│
├─> 游戏结束处理
│    ├─> 显示胜负结果
│    └─> 询问是否复盘
│         ├─> 是: 显示完整复盘
│         └─> 否: 退出游戏
│
└─> 程序结束

关键代码实现

1. AI决策核心算法

// α-β剪枝极小极大算法实现
int dfs(int x, int y, int player, int depth, int alpha, int beta, int is_maximizing)
{
    if (depth == 0 || check_win(x, y))
    {
        return evaluate_pos(x, y, player) - evaluate_pos(x, y, 3 - player);
    }
    
    if (is_maximizing)
    {
        int max_eval = INT_MIN;
        for (每个可能位置)
        {
            int eval = dfs(x, y, player, depth-1, alpha, beta, 0);
            max_eval = max(max_eval, eval);
            alpha = max(alpha, eval);
            // α剪枝
            if (beta <= alpha)
            {
               break;  
            }
        }
        return max_eval;
    } 
    else
    {
        int min_eval = INT_MAX;
        for (每个可能位置)
        {
            int eval = dfs(x, y, player, depth-1, alpha, beta, 1);
            min_eval = min(min_eval, eval);
            beta = min(beta, eval);
            // β剪枝
            if (beta <= alpha)
            {
                break;
            }  
        }
        return min_eval;
    }
}

2. 棋型评估函数

// 评估特定位置的棋型价值
int evaluate_pos(int x, int y, int player)
{
    int score = 0;
    for (四个方向)
    {
        ChessPattern pattern =count_specific_direction(x, y, dir);
        
        if (pattern.continuous_chess >= 5)
        {
            return 1000000; // 五连珠
        }    
        
        // 活棋
        if (pattern.check_start && pattern.check_end)
        {   
            if (pattern.continuous_chess == 4) 
                score += 100000; // 活四
            else if (pattern.continuous_chess == 3)
                score += 5000; // 活三
            else if (pattern.continuous_chess == 2)
                score += 500; // 活二
        } 
        // 眠棋
        else if (pattern.check_start || pattern.check_end)
        {   
            if (pattern.continuous_chess == 4)
                score += 10000; // 冲四
            else if (pattern.continuous_chess == 3)
                score += 1000; // 眠三
            else if (pattern.continuous_chess == 2)
                score += 100; // 眠二
        }
    }
    return score;
}

3. 胜负判断逻辑

// 检查是否形成五连珠
int check_win(int x, int y)
{
    for (四个方向)
    {
        int count = 1;
        // 正向检查
        for (int i = 1; i < 5; i++)
        {
            if (棋盘边界检查 || 棋子不连续)
            { 
                break;
            }
            count++;
        }
        // 反向检查
        for (int i = 1; i < 5; i++)
        {
            if (棋盘边界检查 || 棋子不连续)
            {
                break;
            } 
            count++;
        }
        // 五连珠
        if (count >= 5)
        {
            return 1;
        }
    }
    return 0;
}

项目结构

  • 五子棋 copy 3.c - 主程序文件(当前使用版本)
  • 其他五子棋 copy*.c文件为开发过程中的不同版本

注意事项

  1. 编译时需要链接数学库(-lm
  2. 确保输入坐标在棋盘范围内
  3. AI思考时间随棋盘大小和搜索深度增加

详细技术实现说明

1. 主函数(main)执行流程

  1. 初始化阶段

    • 提示用户输入棋盘尺寸(5-25),默认15x15
    • 初始化棋盘状态(全空)
    • 打印初始空棋盘
  2. 游戏主循环

    • 玩家回合
      • 提示玩家输入坐标(行列格式)
      • 验证坐标有效性(是否在棋盘范围内且为空位)
      • 在棋盘放置玩家棋子(X)
      • 检查是否形成五连珠(玩家胜利)
    • AI回合
      • 调用ai_move()计算最佳落子位置
      • 在棋盘放置AI棋子(○)
      • 检查是否形成五连珠(AI胜利)
    • 平局检查
      • 当棋盘已满且无胜负时判定平局
  3. 游戏结束处理

    • 显示最终胜负结果
    • 提供复盘功能(逐步展示整个对局过程)

2. AI决策系统(ai_move)

防御策略

  1. 优先检查玩家可能形成的威胁棋型:
    • 活四(必须立即阻挡)
    • 冲四(一端被堵的四连珠)
    • 活三(两端开放的三连珠)

进攻策略

  1. 使用α-β剪枝优化的极小极大算法:

    • 搜索深度:3层
    • 评估函数:evaluate_pos()差值
    • 剪枝条件:alpha ≥ beta时终止搜索
  2. 搜索优化:

    • 仅考虑已有棋子周围2格范围内的空位
    • 中心位置奖励(棋盘中心区域价值更高)
    • 对称位置剪枝(减少重复计算)

3. 棋型评估系统(evaluate_pos)

评分标准详细说明

  1. 活棋(两端开放)

    • 活四:100000分(必胜)
    • 活三:5000分(高威胁)
    • 活二:500分(潜在威胁)
  2. 眠棋(一端开放)

    • 冲四:10000分(次高威胁)
    • 眠三:1000分(中等威胁)
    • 眠二:100分(低威胁)
  3. 死棋(两端封闭)

    • 无威胁价值,仅基础分
  4. 位置奖励

    • 中心区域:额外加分(50*(BOARD_SIZE-距离))
    • 边角区域:基础分

评估过程

  1. 四个方向(水平、垂直、对角线)分别评估
  2. 综合最高分方向和所有方向加权分
  3. 考虑当前玩家和对手的分数差值

4. 胜负判断(check_win)

实现细节

  1. 四个方向检查:

    • 水平(→)
    • 垂直(↓)
    • 主对角线(↘)
    • 副对角线(↙)
  2. 检查逻辑:

    • 从当前位置向两个方向延伸
    • 统计连续同色棋子数
    • 任一方向≥5即判定胜利
  3. 优化措施:

    • 边界检查避免数组越界
    • 提前终止(发现5连立即返回)

5. 复盘系统(review_process)

实现机制

  1. 数据结构:

    • 使用steps数组记录每一步落子
    • 包含玩家类型、坐标信息
  2. 回放过程:

    • 逐步重建棋盘状态
    • 显示每一步的落子位置
    • 支持暂停/继续控制
  3. 可视化:

    • 清晰的棋盘显示
    • 回合计数和玩家标识
    • 坐标转换(0-base转1-base)

6. 方向分析(count_specific_direction)

算法细节

  1. 输入参数:

    • 起始坐标(x,y)
    • 方向向量(dx,dy)
    • 玩家标识
  2. 分析过程:

    • 正向延伸(统计连续棋子)
    • 反向延伸(统计连续棋子)
    • 检查两端开放状态
  3. 输出结构:

    • 连续棋子数
    • 起点开放状态
    • 终点开放状态

应用场景

  1. 胜负判断
  2. 棋型评估
  3. 威胁检测