回忆儿时游戏-井字棋(完整代码)

回忆儿时游戏-井字棋(完整代码)

简介

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

过程

因为最近在学习Python的实训,学习了接近两周了,感觉Python确实是比较简单的,而且具有丰富的第三方库,(手动点赞),进入正题,一周的基础,当然要进行项目了,作为爱玩游戏的我,当然要从游戏入手,通过制作游戏,可以提升你的思维逻辑,其实写代码更多的是你的逻辑,你的思维。废话不多说先看这个游戏的规则已经在简介说了,首先我们需要绘制棋盘,我们需要知道这个棋盘是多大的我们可以尝试输出:

print("""
0 | 1 | 2
---------
3 | 4 | 5
---------
6 | 7 | 8
""")
回忆儿时游戏-井字棋(完整代码)

这是我们要绘制大致棋盘的样式,这样,我们就可以定义如下参数:

# 全局常量
X = "X"
O = "O"
EMPTY = " "
TIE = "TIE"
NUM_SQUARES = 9

前两个变量就是井字棋的两个棋子,然后定义一个空,一个平局,还有棋盘的位置。

下面就是,我们都要思考的,玩一个游戏,你是和电脑玩(暂时没考虑人人对战)。肯定先询问一下,电脑先手还是玩家先手,所以定义一个询问函数,在这里简单说一下,这个的函数定义,很多地方都可以用得到,方便化结构化管理。

# 询问答案”是“或”否“
def ask_yes_no(question):
    response = None
    while response not in ('y', 'n'):
        response = input(question).lower()
    return response

这个就是询问函数返回y/n,下面的函数就是规定落点,棋盘一共九个位置,肯定不能随便下。

# 用户给出指定范围内的一个数字
def ask_number(question, low, high):
    response = None
    # range(low, high)是左闭右开区间
    while response not in range(low, high):
        response = int(input(question))
    return response

下面就是先手的棋子问题,一般认为先走的为X

# 决定玩家和电脑各执哪种棋子
def pieces():
    # 在一个函数内调用另一个函数
    go_first = ask_yes_no("是否玩家先走?(y/n):")
    if go_first == 'y':
        print("玩家先走")
        human = X
        computer = O
    else:
        print("电脑先走")
        computer = X
        human = O
    return computer, human

下面就是绘制棋盘逻辑,其实棋盘就是一个数组,存放。

def new_board():
    board = []
    for i in range(NUM_SQUARES):
        board.append(EMPTY)
    return board

绘制棋盘:

def display_board(board):
    print("\n\t", board[0], "|", 
                  board[1], "|", 
                  board[2])
    print("\t", "-" * 9)
    print("\t", board[3], "|", 
                board[4], "|", 
                board[5])
    print("\t", "---------")
    print("\t", board[6], "|", 
                board[7], "|", 
                board[8])

下面就是下棋的合理性,例如。你再1号位置下了,我肯定不能再下1号位置了。

# 根据当前局面,确保行棋合法
def legal_moves(board):
    moves = []
    for i in range(NUM_SQUARES):
        if board[i] == EMPTY:
            moves.append(i)
    return moves 

胜负状态的判定:

# 判断胜负
# 游戏有四种状态: X获胜,O获胜,平局,正在进行

def winner(board):
    # 获胜的8种可能性:一方占据了以下某一行
    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:
        # WAYS_TO_WIN的某一行都是同一方(O或X)
        # 则该方获胜
        if board[row[0]] == board[row[1]] \
            == board[row[2]] != EMPTY:
            the_winner = board[row[0]]
            return the_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("那里不可以")
    return move

下一个就是电脑下棋的策略:

def computer_move(board, computer, human):
    """
    电脑下棋策略:
    1. 如果有一步可以让电脑在本轮获胜,就选那一步
    2. 如果有一步可以让玩家在下一轮获胜,就堵那一步
    3. 其他情况下,按照方格本身的优先级落子
        中间最好,四角次之,边缘最差
    """

    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

    # 如果不是以上两种情况,则依照BEST_MOVES的顺序落子
    for move in BEST_MOVES:
        if move in legal_moves(board):
            print(move)
            return move


def next_turn(turn):
    if turn == O:
        return X
    else:
        return O

最后提示获胜的状态:

def congrat_winner(the_winner, computer, human):
    if the_winner != TIE:
        print(the_winner, " 获胜!")
    else:
        print("平局!")
        
    if the_winner == computer:
        print("愚蠢的人类")
    elif the_winner == human:
        print("我会回来的")
    elif the_winner == TIE:
        print("咱们走着瞧")

然后就是主函数的编写:

def main():
    computer, human = pieces()  # 人机分配棋子
    turn = X  # X先走
    board = new_board()  # 生成一个新棋盘
    display_board(board)

    # 当胜负未决,winner()返回None
    while not winner(board):
        if turn == human:
            # human_move()返回玩家的落子位置
            move = human_move(board, human)
            # 将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)
    congrat_winner(the_winner, computer, human)

最后运行main函数就OK了

main()

总结

经过简单的小游戏编写测试,把Python的基础巩固好,其实这个游戏,还是牵扯一点点的人工智能, 就是电脑下棋的策略都是最优算法,目前Python做人工智能也是比较火热的。


已发布

分类

来自

标签:

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注