井字棋游戏

井字棋游戏,第1张

  • 案例目的

本章案例研究,通过井字棋游戏案例帮助读者深入了解,使用数据结构和算法实现游戏,人工智能井字棋游戏包括较为复杂的计算机人工智能落子算法,判断输赢算法等,通过把不同功能定义为独立的函数,可以减少程序的复杂性。

  • 案例内容

井字棋,英文名叫Tic-Tac-Toe,是一种在3*3格子上进行的连珠游戏,和五子棋类似,由于棋盘一般不画边框,格线排成井字故得名。游戏需要的工具仅为纸和笔,然后由分别代表O和X的两个游戏者轮流在格子里留下标记(一般来说先手者为X),任意三个标记形成一条直线,则为获胜。

表 1棋谱类型("+"是指“眼”)

A型(O胜)

B型(X胜)

C型(O胜)

 

 

 

三、  

~ 实验环境

Pycharm、Anaconda

四、设计实现

4.1 设计思路

        棋盘采用包含3*3个元素的列表来表示,board[o]到board[8]存储代表棋子的字符串,字符串中可以包含"X"、"O"、或者数字0到8(表示未落子)。

程序的流程如下:

        (1)初始化棋盘;

        (2)询问玩家选择棋子:棋子X先走,棋子0后走;

        (3)显示棋盘及落子布局(调用函数display_board() ) ;

        (4)循环轮流落子:

                (4-1)如果玩家落子,则询问落子位置(调用函数getPlayerMove() ,然后判断玩家是否获胜(调用函数isWinner() ) ,如果获胜,显示棋盘(调用函数display_board()),输出信息,break跳出循环;

                (4-2)如果计算机人工智能(AI)落子,则根据计算机人工智能(AI)落子算法计算落子位置,然后判断AI是否获胜(调用函数isWinner()),如果AI获胜,则显示棋盘(调用函数display_board()),输出信息, break跳出循环;

                (4-3)判断是否平局(调用函数isTie()),如果平局,则显示棋盘(调用函数display_board()),输出信息,break跳出循环;否则继续轮流落子。

计算机人工智能(AI)落子算法如下:

        (1)如果某位置落子可以获胜,则选择该位置;

        (2)否则,如果某个位置玩家下一步落子可以获胜,则选择该位置;

        (3)否则,按中心(4)、角(0、2、6、8)、边(1、3、5、7)顺序选择空的位置。

判断输赢规则如下:如果三条横线((0,1,2),(3,4,5),(6,7,8))、三条竖线((0,3,6),(1,4,7),(2,5,8))、两条对角线((0,4,8),(2,4,6))共八种情况的三个位置的棋子相同,则该棋子方赢棋。如果全部位置落子,则平局。

 图 1 井字棋流程

4.2 代码实现

def display_board(b): 

    """显示棋盘""" 

    print("\t{0}|{1}|{2}".format(b[0], b[1], b[2])) 

    print("\t_|_|_") 

    print("\t{0}|{1}|{2}".format(b[3], b[4], b[5])) 

    print("\t_|_|_") 

    print("\t{0}|{1}|{2}".format(b[6], b[7], b[8])) 

 

def legal_moves(board): 

    """返回可下棋的位置列表""" 

    moves = [] 

    for i in range(9): 

        if board[i] in list("012345678"): 

            moves.append(i) 

    return moves 

 

 

def getPlayerMove(board): 

    """询问并确定玩家(player)选择落子位置,无效位置时重复询问""" 

    move = 9  # 初始值9为错误的位置 

    while move not in legal_moves(board): 

        move = int(input("请选择落子位置(0-8):")) 

    return move 

 

 

def getComputerMove(board, computerLetter, playerLetter): 

    """计算人工智能AI的落子位置, Tic Tac Toe AI核心算法""" 

    boardcopy = board.copy()  # 拷贝棋盘,不影响原来 

    # 规则1:判断如果某位置落子可获胜,则选择该位置 

    for move in legal_moves(boardcopy): 

        boardcopy[move] = computerLetter 

        if isWinner(boardcopy, computerLetter):  # 判断是否获胜 

            return move 

        boardcopy[move] = str(move) 

 

    # 规则2:某个位置玩家下一步落子可获胜,则选择该位置 

    for move in legal_moves(boardcopy): 

        boardcopy[move] = playerLetter 

        if isWinner(boardcopy, playerLetter):  # 判断是否获胜 

            return move 

        boardcopy[move] = str(move) 

    # 规则2:中心(4)、角(0、2、6、8)、边(1、3、5、7)顺序选择空的位置 

    for move in (4, 0, 2, 6, 8, 1, 3, 5, 7): 

        if move in legal_moves(board): 

            return move 

 

 

def isWinner(board, letter): 

    """判断所给的棋子是否获胜""" 

    WAYS_TO_WIN = {(0, 1, 2), (3, 4, 5), (6, 7, 8), (0, 3, 6), (1, 4, 7), (2, 5, 8), 

                   (0, 4, 8), (2, 4, 6)} 

    for r in WAYS_TO_WIN: 

        if board[r[0]] == board[r[1]] == board[r[2]]: 

            return True 

    return False 

 

 

def isTie(board): 

    """判断是否平局""" 

    for i in list("012345678"): 

        if i in board: 

            return False 

    return True 

 

 

def tic_tac_toe(): 

    """井字棋""" 

    # 初始化棋盘为['0', '1', '2', '3', '4', '5', '6', '7', '8'] 

    board = list("012345678") 

    # 询问玩家选择棋子:棋子X先走,棋子O后走 

    playerLetter = input("请选择棋子X或O(X先走,O后走):") 

    if playerLetter in ("X", "x"): 

        turn = "player"  # 玩家先走 

        computerLetter = "O" 

    else: 

        turn = "computer" 

        computerLetter = "X" 

        playerLetter = "O" 

    print("{}先走!".format(turn)) 

 

    while True:  # 循环轮流落子 

        display_board(board) 

        if turn == 'player':  # 玩家落子 

            move = getPlayerMove(board)  # 询问落子位置 

            board[move] = playerLetter  # 落子 

            if isWinner(board, playerLetter):  # 判断是否获胜 

                display_board(board) 

                print('恭喜玩家获胜!') 

                break 

            else: 

                turn = "computer" 

        else:  # 计算机落子 

            # 计算机落子位置 

            move = getComputerMove(board, computerLetter, playerLetter) 

            print("计算机人工智能AI落子位置:", move) 

            board[move] = computerLetter  # 落子 

            if isWinner(board, computerLetter):  # 判断是否获胜 

                display_board(board) 

                print('计算机人工智能AI获胜!') 

                break 

            else: 

                turn = "player" 

                # 判断是否平局 

        if isTie(board): 

            display_board(board) 

            print('平局!') 

            break 

 

 

if __name__ == '__main__': 

    tic_tac_toe() 

4.3 测试结果

          

 

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/867641.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-12
下一篇 2022-05-12

发表评论

登录后才能评论

评论列表(0条)

保存