Python实现井字棋:基于随机落子与递归逻辑的完整代码解析

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

本文介绍如何使用Python实现一个简易的井字棋游戏。代码采用随机落子策略模拟电脑对手,利用递归函数处理无效落子,并通过嵌套循环检测棋盘胜负状态。文章提供完整的Python源码,涵盖初始化、人机交互、胜负判定及平局处理,适合初学者理解基础游戏逻辑与列表操作。

井字棋游戏实现思路

井字棋(Tic-Tac-Toe)是一个经典的两人对战游戏,目标是在3x3的棋盘上率先连成一条线(横、竖或对角线)。为了简化实现,本示例未引入复杂的博弈算法(如Minimax),而是采用随机落子的方式模拟电脑对手。当电脑随机选择的坐标已被占用时,程序会通过递归重新生成随机坐标,直到找到空位为止。

核心逻辑与代码结构

游戏的核心由以下几个部分组成:棋盘初始化、随机落子逻辑、胜负判定以及人机交互流程。

1. 棋盘初始化与显示

使用二维列表 board 存储棋盘状态,初始值均为 '+'。函数 oput(board) 负责打印当前棋盘状态,包含坐标索引以便用户输入。

2. 电脑随机落子(递归处理)

函数 ma(board) 负责电脑回合。它通过 random.randint(0, 2) 生成随机坐标 (a, b)。如果该位置已被占用(不为 '+'),则递归调用自身重新生成坐标,直到找到空位并落子为 'O'。

3. 胜负判定

函数 test(board) 遍历棋盘所有格子,检查是否存在连续三个相同符号('X' 或 'O')。检查范围包括:

  • 横向:同一行的连续三个格子。
  • 纵向:同一列的连续三个格子。
  • 对角线:主对角线和副对角线。

若检测到胜利条件,调用 winput(i,j) 输出获胜者并返回标志位 1。

4. 游戏主循环

main() 函数控制游戏流程。用户可选择先手('Y')或后手('N')。游戏通过 isempty(board) 判断棋盘是否已满,若满且无胜者则判定为平局。

完整Python代码

以下是实现上述逻辑的完整代码。请注意,代码中使用了递归处理无效落子,这在极端情况下可能导致栈溢出,但在3x3小棋盘上完全可行。

import random

# 初始化3x3棋盘,初始值为'+'
board = [['+','+','+'],['+','+','+'],['+','+','+']]

def ma(board):
    """电脑随机落子,若位置被占用则递归重试"""
    if isempty(board):
        a = random.randint(0, 2)
        b = random.randint(0, 2)
        # 如果随机位置已被占用,递归重新选择
        if board[a][b] != 'X' and board[a][b] != 'O':
            print("机器走:")
            board[a][b] = 'O'
            oput(board)
        else:
            ma(board)
    else:
        print("平局")

def oput(board):
    """打印当前棋盘状态"""
    print("  0 1 2")
    for i in range(3):
        print(i, end=' ')
        for j in range(3):
            print(board[i][j], end=" ")
        print("")

def winput(i,j):
    """判定胜负并输出结果"""
    if board[i][j] == 'X':
        print("human win")
    else:
        print("machine win")
    return 1

def test(board):
    """检查棋盘是否存在获胜条件"""
    for i in range(3):
        for j in range(3):
            if board[i][j] != '+':
                # 检查横向胜利
                if j == 0:
                    if board[i][j] == board[i][j + 1] == board[i][j + 2]:
                        return winput(i,j)
                # 检查纵向胜利
                if i == 0:
                    if board[i][j] == board[i + 1][j] == board[i + 2][j]:
                        return winput(i,j)
                # 检查主对角线胜利
                if i == 0 and j == 0:
                    if board[i][j] == board[i + 1][j + 1] == board[i + 2][j + 2]:
                        return winput(i,j)
                # 检查副对角线胜利
                if i == 2 and j == 0:
                    if board[i][j] == board[i - 1][j + 1] == board[i - 2][j + 2]:
                        return winput(i,j)
    return 0

def isempty(board):
    """检查棋盘是否还有空位"""
    for i in range(3):
        for j in range(3):
            if board[i][j] == '+':
                return True
    return False

def main():
    print("初始棋盘:")
    oput(board)
    flag = 0
    t = input("human first? Y/N  human for X, machine for O\n")
    
    if t == 'Y':
        # 用户先手
        while isempty(board):
            print("人走:  ")
            try:
                a, b = map(int, input("输入落子纵横坐标: a,b \n").split(','))
                if 0 <= a <= 2 and 0 <= b <= 2:
                    if board[a][b] == '+':
                        board[a][b] = 'X'
                        oput(board)
                        flag = test(board)
                        if flag == 1:
                            break
                    else:
                        print("落子位置不对")
                        continue
                else:
                    print("坐标超出范围")
                    continue
            except ValueError:
                print("输入格式错误,请输入两个整数")
                continue
            
            # 电脑回合
            ma(board)
            flag = test(board)
            if flag == 1:
                break
            if isempty(board) == 0 and flag == 0:
                print("平局")
                break
                
    elif t == 'N':
        # 电脑先手
        while isempty(board):
            ma(board)
            flag = test(board)
            if isempty(board) == 0 and flag == 0:
                print("平局")
                break
            if flag == 1:
                break
            
            print("人走:  ")
            try:
                a, b = map(int, input("输入落子纵横坐标: a,b \n").split(','))
                if 0 <= a <= 2 and 0 <= b <= 2:
                    if board[a][b] == '+':
                        board[a][b] = 'X'
                        oput(board)
                        flag = test(board)
                        if flag == 1:
                            break
                    else:
                        print("落子位置不对")
                        continue
                else:
                    print("坐标超出范围")
                    continue
            except ValueError:
                print("输入格式错误,请输入两个整数")
                continue

if __name__ == "__main__":
    main()

注意事项与优化建议

虽然上述代码能正常运行,但存在几个可优化点:

  • 递归深度:当棋盘接近满时,ma 函数的递归调用次数可能增加。虽然3x3棋盘最多只有9个格子,递归深度可控,但在更大棋盘上应避免使用递归。
  • 输入验证:原文代码未处理非整数输入或越界坐标。建议在 main 函数中加入 try-except 块和边界检查,防止程序崩溃。
  • 胜负判定效率:当前 test 函数遍历所有格子,时间复杂度为O(1)(固定9次循环),效率足够。若棋盘扩大,可考虑只检查最后一步落子周围的区域。

通过调整 random 模块或引入更复杂的AI算法(如Minimax),可以进一步提升电脑对手的智能程度。

以上就是Python实现简单的井字棋的详细内容,更多关于Python游戏开发、随机算法与递归应用的相关资料请关注本站其它相关文章!

本站声明

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

Python 相关产品和应用

全部下载

专题列表