一、井子棋介绍

井字棋(Tic Tac Toe),又称井字游戏、"连城"游戏、OX棋,是一种供两人玩的纸笔游戏。两个玩家轮流在九个空格中画上代表自己的O或X,谁先将自己的符号连成一线(横连、竖连、斜连皆可),即获得胜利。倘若在游戏过程中,双方都采取最佳策略,那么游戏往往会以平局告终。

二、需求分析

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

程序的流程如下:
(1)初始化棋盘﹔
(2)询间玩家选择棋子:棋子x先走,棋子o后走;
(3)显示棋盘及落子布局(调用函数display_board() ) ;
(4)循环轮流落子:
(4-1)如果玩家落子,则询问落子位置(调用函数human_move(),然后判断玩家是否获胜(调用函数winner()),如果获胜,显示棋盘(调用函数display_board(),输出信息,break跳出循环;
(4-2)如果计算机人工智能(AI)落子,则根据计算机人工智能(AI)落子算法计算落子位置,然后判断AI是否获胜(调用函数wirner(),如果AI获胜,则显示棋盘(调用函数display_board()),输出信息,break跳出循环;
(4-3)判断是否平局(调用函数wirner(),如果平局,则显示棋盘没有空位置,输出信息,break跳出循环;否则继续轮流落子。

计算人工智能(AI)落子算法如下:
(1)如果某位置落子可以获胜,则选择该位置;
(2)否则,如果某个位置玩家下一步落子可以获胜,则选择该位置;
(3)否则,按中心(4)、角(0、2、6、8)、边(1、3、5、7)顺序选择空的位置。

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

三、代码

# Tic-Tac-Toe 井字棋游戏
# 全局常量
X = "X"
O = "O"
EMPTY = " "


# 询问是否继续
def ask_yes_no(question):
    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


# 询问谁先走,先走方为X,后走方为O
# 函数返回计算机方,玩家的角色代号
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(9):
        board.append(EMPTY)
    return board


# 显示棋盘
def display_board(board):
    board2 = board[:]
    for i in range(len(board)):
        if board[i] == EMPTY:
            board2[i] = i
    print("\t", board2[0], "|", board2[1], "|", board2[2])
    print("\t", "----------")
    print("\t", board2[3], "|", board2[4], "|", board2[5])
    print("\t", "----------")
    print("\t", board2[6], "|", board2[7], "|", board2[8], "\n")
    # 产生可以合法走棋位置序列(也就是还未下过子位置)


def legal_moves(board):
    moves = []
    for square in range(9):
        if board[square] == EMPTY:
            moves.append(square)
    return moves


def winner(board):
    """
    判断输赢
    所有赢得可能情况,例如(0,1,2)就是第一行,(0,4,8,),(2,4,6)就是对角线
    """
    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 False


def human_move(board, human):
    """人走棋"""
    legal = legal_moves(board)
    move = None
    while move not in legal:
        move = ask_number("你走那个位置?(0-8):", 0, 9)
        if move not in legal:
            print("\n此位置已经落过子了")
            # print("Fine...")
    return move


def computer_move(board, computer, human):
    """
    计算机走棋
     按优劣顺序排序的下棋走子
     最佳下棋位置顺序表(4,0,2,6,8,1,3,5,7)
    """
    board = board[:]
    BEST_MOVES = (4, 0, 2, 6, 8, 1, 3, 5, 7)
    # 如果计算机能赢,就走那个位置
    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 main():
    """主函数"""
    computer, human = pieces()
    turn = 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)
    if the_winner == computer:
        print("计算机赢!\n")
    elif the_winner == human:
        print("玩家赢!\n")
    elif the_winner == "TIE":
        print("平局,游戏结束\n")

main()
input("按任意键退出游戏")

四、运行结果

在这里插入图片描述

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐