用Python和Pygame从零打造一个能‘思考’的五子棋AI(附完整代码)

五子棋作为一款经典策略游戏,其规则简单却蕴含无限变化。许多开发者尝试用编程实现人机对战,但要让AI具备基本"思考"能力并非易事。本文将带你从零开始,使用Python和Pygame构建一个能分析局势、做出决策的五子棋AI,完整代码可直接运行测试。

1. 环境准备与基础框架搭建

在开始编码前,我们需要配置开发环境并建立游戏基础框架。这个阶段将完成棋盘绘制、棋子显示等视觉部分。

首先安装必要的库:

pip install pygame numpy

初始化Pygame窗口并绘制棋盘:

import pygame
import numpy as np

def init_game():
    pygame.init()
    screen = pygame.display.set_mode((615, 615))
    pygame.display.set_caption('五子棋AI')
    screen.fill("#DD954F")  # 棋盘底色
    
    # 绘制棋盘网格线
    for i in range(19):
        # 横线
        pygame.draw.line(screen, '#000000', (30, 30 + i*32), (594, 30 + i*32), 1)
        # 竖线
        pygame.draw.line(screen, '#000000', (30 + i*32, 30), (30 + i*32, 594), 1)
    
    # 绘制星位标记
    star_positions = [(3,3), (9,3), (15,3), (3,9), (9,9), 
                     (15,9), (3,15), (9,15), (15,15)]
    for x, y in star_positions:
        pygame.draw.circle(screen, '#000000', (30 + x*32, 30 + y*32), 5)
    
    pygame.display.flip()
    return screen

棋盘状态用19x19的二维数组表示:

board = np.zeros((19, 19))  # 0:空 1:黑棋 2:白棋

2. 游戏核心逻辑实现

2.1 棋子绘制与落子判定

设计棋子绘制函数需要考虑视觉效果和状态记录:

def draw_piece(screen, x, y, color):
    """绘制棋子
    :param x: 棋盘横坐标(0-18)
    :param y: 棋盘纵坐标(0-18)
    :param color: 'black'或'white'
    """
    center = (30 + x*32, 30 + y*32)
    if color == 'black':
        pygame.draw.circle(screen, (45, 45, 45), center, 15)
        pygame.draw.circle(screen, (80, 80, 80), center, 12)
    else:
        pygame.draw.circle(screen, (230, 230, 230), center, 15)
        pygame.draw.circle(screen, (200, 200, 200), center, 12)
    pygame.display.update()

鼠标点击处理逻辑:

def handle_click(pos, board, current_player):
    """处理玩家点击事件
    :return: (x, y) 落子位置,None表示无效点击
    """
    x, y = (pos[0]-30)//32, (pos[1]-30)//32
    if 0 <= x < 19 and 0 <= y < 19 and board[x][y] == 0:
        board[x][y] = 1 if current_player == 'black' else 2
        return x, y
    return None

2.2 胜负判定算法

五子棋胜负判定需要检查四个方向(水平、垂直、对角线)是否有五连珠:

def check_win(board, x, y):
    """检查是否获胜
    :return: True/False
    """
    directions = [(1,0), (0,1), (1,1), (1,-1)]  # 四个检查方向
    player = board[x][y]
    
    for dx, dy in directions:
        count = 1  # 当前棋子已算1个
        
        # 正向检查
        nx, ny = x + dx, y + dy
        while 0 <= nx < 19 and 0 <= ny < 19 and board[nx][ny] == player:
            count += 1
            nx += dx
            ny += dy
            
        # 反向检查
        nx, ny = x - dx, y - dy
        while 0 <= nx < 19 and 0 <= ny < 19 and board[nx][ny] == player:
            count += 1
            nx -= dx
            ny -= dy
            
        if count >= 5:
            return True
    return False

3. AI核心算法设计

3.1 模式匹配策略

我们采用模式匹配方法让AI识别棋局形势。定义常见棋型及其优先级:

PATTERNS = [
    # 活四 (优先级最高)
    {'pattern': [0, 1, 1, 1, 1, 0], 'score': 10000},
    # 冲四
    {'pattern': [0, 1, 1, 1, 1, 2], 'score': 1000},
    {'pattern': [2, 1, 1, 1, 1, 0], 'score': 1000},
    # 活三
    {'pattern': [0, 1, 1, 1, 0, 0], 'score': 500},
    # 眠三
    {'pattern': [2, 1, 1, 1, 0, 0], 'score': 200},
    # 活二
    {'pattern': [0, 1, 1, 0, 0, 0], 'score': 100},
    # 眠二
    {'pattern': [2, 1, 1, 0, 0, 0], 'score': 50}
]

3.2 局势评估函数

AI需要评估棋盘每个位置的潜在价值:

def evaluate_position(board, x, y, player):
    """评估某个位置的潜在价值
    :return: 该位置得分
    """
    if board[x][y] != 0:  # 已有棋子
        return 0
        
    directions = [(1,0), (0,1), (1,1), (1,-1)]
    total_score = 0
    
    for dx, dy in directions:
        line = []
        # 获取该方向上的6个位置
        for i in range(-2, 4):
            nx, ny = x + i*dx, y + i*dy
            if 0 <= nx < 19 and 0 <= ny < 19:
                line.append(board[nx][ny])
            else:
                line.append(2)  # 边界视为对手棋子
        
        # 匹配预定义模式
        for pattern in PATTERNS:
            if line == pattern['pattern']:
                total_score += pattern['score']
                break
                
    return total_score

3.3 AI决策算法

AI通过评估整个棋盘选择最佳落子位置:

def ai_move(board):
    """AI选择最佳落子位置
    :return: (x, y) 坐标
    """
    best_score = -1
    best_move = None
    
    # 遍历整个棋盘
    for x in range(19):
        for y in range(19):
            if board[x][y] == 0:
                # 评估进攻价值(AI视角)
                attack_score = evaluate_position(board, x, y, 2)
                # 评估防守价值(玩家视角)
                defend_score = evaluate_position(board, x, y, 1)
                # 综合得分
                total_score = attack_score + defend_score * 0.8
                
                if total_score > best_score:
                    best_score = total_score
                    best_move = (x, y)
    
    # 如果没有找到策略点,随机选择
    if best_move is None:
        empty_pos = [(x,y) for x in range(19) for y in range(19) if board[x][y]==0]
        return random.choice(empty_pos) if empty_pos else None
    
    return best_move

4. 游戏主循环与完整实现

将各部分组合成完整游戏:

def main():
    screen = init_game()
    board = np.zeros((19, 19))
    current_player = 'black'  # 黑棋先行
    game_over = False
    
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                return
                
            if not game_over and current_player == 'black' and event.type == pygame.MOUSEBUTTONDOWN:
                pos = handle_click(event.pos, board, current_player)
                if pos:
                    x, y = pos
                    draw_piece(screen, x, y, current_player)
                    if check_win(board, x, y):
                        print("玩家获胜!")
                        game_over = True
                    current_player = 'white'
                    
        # AI回合
        if not game_over and current_player == 'white':
            pygame.time.delay(500)  # AI思考时间
            pos = ai_move(board)
            if pos:
                x, y = pos
                board[x][y] = 2
                draw_piece(screen, x, y, current_player)
                if check_win(board, x, y):
                    print("AI获胜!")
                    game_over = True
                current_player = 'black'

if __name__ == "__main__":
    main()

5. 进阶优化方向

基础版本完成后,可以考虑以下优化:

  1. 增加难度级别

    • 初级:随机落子
    • 中级:当前模式匹配
    • 高级:加入Minimax搜索算法
  2. 性能优化

    # 使用局部搜索代替全局搜索
    def get_neighbor_positions(board, radius=2):
        """获取已有棋子周围的位置"""
        positions = set()
        for x in range(19):
            for y in range(19):
                if board[x][y] != 0:
                    for i in range(-radius, radius+1):
                        for j in range(-radius, radius+1):
                            nx, ny = x+i, y+j
                            if 0 <= nx < 19 and 0 <= ny < 19 and board[nx][ny] == 0:
                                positions.add((nx, ny))
        return positions if positions else None
    
  3. 增加开局库

    • 预置常见开局模式
    • 提高AI开局阶段的表现
  4. 可视化评估

    def draw_evaluation(screen, board):
        """绘制棋盘各点评估值(调试用)"""
        font = pygame.font.SysFont('arial', 10)
        for x in range(19):
            for y in range(19):
                if board[x][y] == 0:
                    score = evaluate_position(board, x, y, 2)
                    if score > 0:
                        text = font.render(str(score), True, (255,0,0))
                        screen.blit(text, (30 + x*32 - 10, 30 + y*32 - 5))
        pygame.display.update()
    

这个五子棋AI实现展示了如何将游戏规则转化为计算机可执行的逻辑。虽然不如专业棋类AI强大,但核心思路相同:评估局势、预测发展、选择最优策略。读者可以在此基础上继续扩展,比如加入深度学习等更先进的算法。

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐