python 纯函数实现井字棋游戏

1、定义全局变

'''全局变量:
 X 和 O 表示两方的棋子;
 EMPTY 表示棋位为空;
 TIE 表示平局;
 NUM_SQUARES 表示有 9 个棋位
 '''
 
 X = "X"
 O = "O"
 EMPTY = " "
 TIE = "TIE"
 NUM_SQUARES = 9

2、定义调用到的函数

def ask_yes_no(question):
    '''问一个是或否的问题,用 y 或 n 回答。'''
    response = None
    while response not in ('y', 'n'):
        response = input(question).lower()
    return response


def ask_number(question, low, high):
    '''讯问一个规定范围的数字。'''
    response = None
    while response not in range(low, high):
        response = int(input(question))
    return response


def pieces():
    '''决定在人和机器之间谁先行棋。'''
    go_first = ask_yes_no('你先走? (y/n): ')
    if go_first == 'y':
        print('\n好,你先请。')
        human = X
        computer = O
    else:
        print('\n你放弃先手,我先走。')
        computer = X
        human = O
    return computer, human


def new_board():
    '''创建一个棋盘。'''
    board = []
    for square in range(NUM_SQUARES):
        board.append(EMPTY)
    return board


def display_board(board):
    '''显示棋盘。'''
    print('\n\t', board[0], '|', board[1], '|', board[2])
    print('\t', '---------')
    print('\t', board[3], '|', board[4], '|', board[5])
    print('\t', '---------')
    print('\t', board[6], '|', board[7], '|', board[8], '\n')


def legal_moves(board):
    '''创建合法的行棋位置清单。'''
    moves = []
    for square in range(NUM_SQUARES):
        if board[square] == EMPTY:  # 该棋位为空
            moves.append(square)
    return moves


def winner(board):
    '''判定游戏获胜者。'''
    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 row in WAYS_TO_WIN:
        if board[row[0]] == board[row[1]] == board[row[2]] != EMPTY:
            winner = board[row[0]]
            return winner
    
    # 没有获胜方,但棋盘已经下满,判为平局
    if EMPTY not in board:
        return TIE

    return None  # 没有获胜方,且非平局


def human_move(board, human):
    '''获取玩家的行棋位置。'''  
    legal = legal_moves(board)  # 合法的行棋位置清单
    move = None
    while move not in legal:
        move = ask_number('你走哪? (0 - 8):', 0, NUM_SQUARES)
        if move not in legal:
            print('\n你选的棋位已落子,重新选择。\n')
    print('落子无悔...')
    return move


def computer_move(board, computer, human):
    '''获取电脑的行棋位置。'''
    
    board = board[:]  # 通过切片复制棋盘, 创建局部变量
    BEST_MOVES = (4, 0, 2, 6, 8, 1, 3, 5, 7)  # 优先的行棋位置

    print('我走到:', end=' ')
    
    # 在局部空间确定可以获胜的走法
    for move in legal_moves(board):  # 合法的行棋位置列表
        board[move] = computer  # 更新棋盘副本
        if winner(board) == computer:
            # 计算机能获胜
            print(move)
            return move
        # 如果计算机在该棋位行棋不能获胜,
        board[move] = EMPTY  # 悔棋,更换下一个合法棋位
    
    # 阻止玩家获胜
    for move in legal_moves(board):  # 合法的行棋位置列表
        board[move] = human  # 更新棋盘
        if winner(board) == human:
            # 在该棋位玩家行棋后将获胜
            print(move)
            return move
        # 玩家不能获胜,不行棋至此
        board[move] = EMPTY

    # 没有能使行棋双方立决胜负的棋位,从优先棋位选择合法行棋位置
    for move in BEST_MOVES:
        if move in legal_moves(board):
            print(move)
            return move


def next_turn(turn):
    '''切换行棋方'''
    if turn == X:
        return O
    else:
        return X

    
def congrat_winner(the_winner, computer, human):
    '''向获胜方表示祝贺或声明平局'''
    if the_winner != TIE:
        print(the_winner, '祝贺你!\n')
    else:
        print('平局。。。\n')

    if the_winner == computer:
        print('如我所料,我又胜了。\n这是否能说明计算机在给方面都优于人类呢?')

    elif the_winner == human:
        print('真是匪夷所思,你没捣鬼吧?人类怎么会胜? \n不会有下次了。' )

    elif the_winner == TIE:
        print('你很厉害嘛,能跟计算机打成平手。')

3、定义主函数

 

def main():
    display_instruct()  # 显示游戏操作指南
    computer, human = pieces()  # 决定谁先行棋
    turn = X  # 先行棋方执子 X
    board = new_board()  # 创建空棋盘
    display_board(board) # 显示棋盘

    while not winner(board): 
        # 判定结果,在没有获胜方且不是平局时进入循环
        if turn == human:
            # 轮到玩家行棋,玩家行棋
            move = human_move(board, human)  # 玩家的行棋位置
            board[move] = human  # 更新棋盘
        else:
            # 轮到电脑行棋
            move = computer_move(board, computer, human)  # 电脑的行棋位置
            board[move] = computer  # 更新棋盘
        display_board(board)  # 显示更新后的棋盘
        turn = next_turn(turn)  # 切换行棋方

    the_winner = winner(board)  # 判定获胜者,返回获胜方的执子,平局返回 None
    congrat_winner(the_winner, computer, human)  # 向获胜方表示祝贺或声明是平局

4、调用主函数,启动程序

main()
input('\n\n按回车键退出程序。')  # 等待用户

在 jupyter 中演练如下:

 

 

 

 

 

posted @ 2020-02-02 22:35  赏尔  阅读(716)  评论(0编辑  收藏  举报