Python五子棋小游戏开发:从算法思路到代码实现

Chloe
Chloe
发布时间:2026-10-10 | 2人浏览过
原创

开发一个轻量级的控制台五子棋小游戏,核心任务是将棋盘状态管理、用户落子交互以及五子连珠判定算法整合为清晰可靠的代码结构。本文基于 Python 3 标准库,完整讲解五子棋从数据结构建模、核心判胜算法推导到终端主循环控制的实现过程,帮助你彻底理清游戏逻辑与代码细节。

一、游戏规则解构与数据结构建模

五子棋的标准规则是在 15×15 的网格棋盘上,黑白双方轮流落子,先在横向、纵向或任意一条对角线上连成连续同色五子者获胜。若棋盘全部填满仍未分胜负,则判定为平局。

在 Python 中,建模棋盘最直接且高效的方式是使用嵌套列表(二维数组)。我们可以将棋盘定义为一个大小为 15×15 的列表,每个单元格初始化为空位符号(例如加号“+”或点号“.”)。玩家分别使用特定字符代表棋子,例如黑棋使用“X”,白棋使用“O”。

  • 棋盘坐标系:行号与列号索引范围均为 0 到 14。通过二维索引 board[row][col] 可直接读写指定位置的状态。
  • 终端可视化渲染:通过遍历二维列表逐行打印棋盘,同时在顶部和左侧打印对应的数字行标与列标,便于玩家在终端输入准确的坐标。
  • 落子状态机:游戏维护一个当前执子方的标记,每完成一次有效落子后,自动在黑白双方之间切换。
Python五子棋小游戏开发:从算法思路到代码实现
图 1:Python五子棋小游戏系统架构与模块数据流

二、胜负判定算法:全盘遍历与局部四向扫描差异解析

在五子棋程序开发中,胜负判定的设计直接影响代码的简洁度与运行效率。常见的判决方案主要有两种思路:“全局全盘扫描”与“落子点局部四向扫描”。我们在相同规则条件下对比这两种策略的核心差异及其影响:

对比维度 全局全盘扫描 落子点局部四向扫描(推荐)
触发时机与范围 每次落子后,遍历整个 15×15 棋盘的全部 225 个点 仅以当前刚落下的棋子坐标 (row, col) 为中心向外探测
检查方向与次数 全盘每个点都向右、向下、右下、左下四个方向检查 5 个连续位置 仅对最新落子点进行水平、垂直、正斜、反斜四个轴向的双向探寻
时间复杂度 O(N²),每步需要数百次比对,产生大量冗余空位检查 O(1),单步检查次数至多 4 × 9 = 36 次比对,瞬间完成
逻辑影响与可维护性 容易重复扫描旧棋子,无法精准定位引发胜利的关键手 准确绑定当前行动玩家,落子即判定,代码精简且无副作用

为什么这一差异极为重要?因为在落子前,棋盘处于未分胜负状态,只有新落下的这颗棋子才可能触发“五子连珠”。检查未发生变化的区域完全没有意义。因此,选择局部四向扫描不仅计算量降到了常数级别,还能保证裁决逻辑绝对纯粹。

Python五子棋小游戏开发:从算法思路到代码实现
图 2:五子棋胜负判定核心算法:局部四向探测原理

局部四向扫描的具体执行过程如下:定义四组相互正交的轴向向量:水平轴 (0, 1) 与 (0, -1)、垂直轴 (1, 0) 与 (-1, 0)、正对角线 (1, 1) 与 (-1, -1)、反对角线 (1, -1) 与 (-1, 1)。对于每个轴向,初始连续计数设为 1(即刚落下的这颗棋子),然后分别沿着正向与反向不断延伸:只要相邻坐标未越界且棋子颜色相同,计数器就加 1;一旦遇到异色棋子、空位或棋盘边界,该方向立即停止延伸。如果正反两个方向的连续棋子总数达到或超过 5,即可断定当前玩家获胜。

三、开发与实现步骤拆解

按照自底向上的模块化工程开发思路,我们可以将整个五子棋程序的实现划分为四个有序步骤:

Python五子棋小游戏开发:从算法思路到代码实现
图 3:五子棋小游戏编码开发操作全步骤
  1. 步骤一:棋盘初始化与渲染函数:编写 create_board() 创建 15×15 的空白网格,并编写 print_board(board) 输出美观的棋盘视图,包括横纵坐标刻度。
  2. 步骤二:用户输入捕获与合法性校验:编写 get_valid_move(board, current_player),接收用户输入的行与列,处理非数字输入异常,并检查坐标是否在 0 <= r < 15 和 0 <= c < 15 范围内,同时拦截已被占用的单元格。
  3. 步骤三:四向判决引擎实现:编写 check_win(board, row, col, piece) 函数,基于前文推导的方向向量,对最新落子点进行延伸累加,返回布尔值。
  4. 步骤四:游戏主循环与平局控制:编写 play_game() 函数,管理回合轮转、落子步数累加(当步数达到 225 且无人获胜时宣布平局)以及胜负结果输出。

四、完整 Python 代码实现与运行测试

以下是使用 Python 3 标准库编写的完整可运行代码。该程序无须安装任何第三方依赖,可在标准命令行终端直接执行:

# -*- coding: utf-8 -*-
"""Python 五子棋控制台小游戏完整实现"""

BOARD_SIZE = 15
EMPTY_CELL = '.'
PLAYER_X = 'X'  # 黑方
PLAYER_O = 'O'  # 白方


def create_board():
    """创建初始 15x15 棋盘"""
    return [[EMPTY_CELL for _ in range(BOARD_SIZE)] for _ in range(BOARD_SIZE)]


def print_board(board):
    """打印带有坐标标尺的棋盘"""
    print("\n   " + " ".join(f"{i:2d}" for i in range(BOARD_SIZE)))
    for r in range(BOARD_SIZE):
        row_str = "  ".join(board[r][c] for c in range(BOARD_SIZE))
        print(f"{r:2d}  {row_str}")
    print()


def check_win(board, row, col, piece):
    """以最新落子点为中心,进行四方向局部扫描判定胜负"""
    directions = [
        ((0, 1), (0, -1)),    # 水平方向
        ((1, 0), (-1, 0)),    # 垂直方向
        ((1, 1), (-1, -1)),   # 正斜对角 (左上-右下)
        ((1, -1), (-1, 1))    # 反斜对角 (右上-左下)
    ]

    for d1, d2 in directions:
        count = 1

        # 正向探测延伸
        r, c = row + d1[0], col + d1[1]
        while 0 <= r < BOARD_SIZE and 0 <= c < BOARD_SIZE and board[r][c] == piece:
            count += 1
            r += d1[0]
            c += d1[1]

        # 反向探测延伸
        r, c = row + d2[0], col + d2[1]
        while 0 <= r < BOARD_SIZE and 0 <= c < BOARD_SIZE and board[r][c] == piece:
            count += 1
            r += d2[0]
            c += d2[1]

        # 任一方向达到连续 5 子即宣告胜利
        if count >= 5:
            return True

    return False


def get_player_move(board, current_player):
    """安全获取并校验当前玩家的落子坐标"""
    while True:
        try:
            prompt = f"请玩家 [{current_player}] 输入落子坐标 (行 列,如 7 7): "
            user_input = input(prompt).strip().split()
            if len(user_input) != 2:
                print("输入格式错误!请输入两个以空格分隔的数字。")
                continue

            r, c = int(user_input[0]), int(user_input[1])
            if not (0 <= r < BOARD_SIZE and 0 <= c < BOARD_SIZE):
                print(f"坐标越界!行和列必须在 0 到 {BOARD_SIZE - 1} 之间。")
                continue

            if board[r][c] != EMPTY_CELL:
                print("该位置已有棋子,请重新选择空位落子!")
                continue

            return r, c
        except ValueError:
            print("输入无效!坐标必须为整数,请重新输入。")


def main():
    """五子棋游戏主循环控制"""
    board = create_board()
    current_player = PLAYER_X
    total_moves = 0
    max_moves = BOARD_SIZE * BOARD_SIZE

    print("=" * 45)
    print("      Python 五子棋控制台小游戏")
    print("   玩家 X (黑棋) 先手,玩家 O (白棋) 后手")
    print("=" * 45)

    print_board(board)

    while True:
        r, c = get_player_move(board, current_player)
        board[r][c] = current_player
        total_moves += 1

        print_board(board)

        # 校验最新落子是否达成胜利
        if check_win(board, r, c, current_player):
            print(f"恭喜!玩家 [{current_player}] 连成五子,赢得比赛!\n")
            break

        # 校验是否达成平局
        if total_moves >= max_moves:
            print("棋盘已满,双方握手言和,平局!\n")
            break

        # 切换执子方
        current_player = PLAYER_O if current_player == PLAYER_X else PLAYER_X


if __name__ == "__main__":
    main()

五、边界场景处理与常见问题排查

在实际编码与调试过程中,以下几个边界条件与潜在问题需要特别注意:

防范数组越界错误(IndexError):在 while 循环向外探寻棋子时,必须将边界判断 0 <= r < BOARD_SIZE and 0 <= c < BOARD_SIZE 放在数组访问 board[r][c] 的最左侧。Python 的短路逻辑会确保一旦坐标越界,立刻终止求值,避免触发异常。

  • 跨方向计数污染:必须为每个轴向独立初始化 count = 1。严禁将水平方向累加的计数值带入垂直或斜向的计算中。
  • 长连判定规则:本程序遵循基础五子棋规则,连续棋子达到或超过 5 颗(count >= 5)即视为获胜。在竞技五子棋(连珠规则)中,黑棋长连(六子及以上)属于禁手,如需实现专业规则可在计数等于 5 时判定胜利、超过 5 时判定犯规。
  • 终端坐标对齐:当行数和列数达到两位数(10 到 14)时,单字符打印容易产生视觉错位。代码中使用了 f"{i:2d}" 格式化字符串,保证数字间距均匀一致。

六、核心知识总结与功能进阶路线

通过本文的开发实践,我们完成了一个具备完整控制流的五子棋程序。项目虽小,却涵盖了二维空间数据结构、短路安全探测、向量扫描算法以及终端交互设计的核心工程思想。

Python五子棋小游戏开发:从算法思路到代码实现
图 4:五子棋项目核心知识总结与进阶拓展架构

在此基础之上,你可以继续向以下三个方向深入拓展,将小游戏演进为功能更丰富的项目:

  1. 接入人机对战 AI:编写棋型评估函数(活四、冲四、活三等),结合极大极小值搜索(Minimax)与 Alpha-Beta 剪枝算法,实现具备思考能力的单人对弈模式。
  2. 图形界面化(GUI):使用 Python 内置的 tkinter 库或 pygame 游戏引擎,用鼠标点击事件替代命令行输入,为游戏添加精致的木纹棋盘与棋子落子音效。
  3. 局域网网络对战:利用 socket 套接字编程建立服务端与客户端,通过 JSON 报文传输落子坐标,实现双人跨终端联网对战。
相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表