参考学习:Python实现井字棋游戏

闲扯

井字棋(Tic-Tac-Toe),初高中进行打发时间的一种画x画o的游戏,3*3的格子组成,一方把行列斜行连成相同的就算获胜。

那么怎么利用进行人机对弈这种简单的小游戏那。我们先不急于写代码,先进行思考,程序的实现是进行方便人们的,我们设计井字棋,肯定想让程序智能化,能够最大程度的模拟人,所以我们设计一个无敌的“人”,最后的结果只能是玩家输或者平局,机器必不可能输。

顺着这个思想想,怎么让机器无敌,这个时候就要考虑这个游戏本身了,因为游戏简单,我们很轻松就可以推到想赢所对应的步骤,把这种思想步骤灌输给计算机,让他学习到,想输都难,大概这就是人工智能(AI)吧,不过我们的这个游戏简单,简易的不能准确的称为标准的人工智能,做不到AlphaGo那样可以对战世界冠军,但是总体AlphaGo也是通过不断学习不断增强的。

言归正传,说我们的井字棋。井字棋我们分为0-8,横着排就是这样。

在这里插入图片描述

想要获胜就要:

(第一个下角,后面的下中)(第一个下中,后面的下角)(不然的必定有一个死棋)

设计

棋盘采用包含9个元素的列表来实现

棋盘为board

board[0]到board[8]存储代表棋子的字符串

在这里插入图片描述

字符串0到8代表未落子

字符串XO表示两种棋子,也就是玩家和机器进行下的棋子

程序

1.先有一个棋盘

        棋盘的设计不唯一,可以设计多种样式的棋盘,有兴趣的话可以进行自行探索。

board = list("012345678")
def dis_board(board):
    #显示出棋盘
    print("\t{0} | {1} | {2}".format(board[0], board[1], board[2]))
    print("\t_ | _ | _")
    print("\t{0} | {1} | {2}".format(board[3], board[4], board[5]))
    print("\t_ | _ | _")
    print("\t{0} | {1} | {2}".format(board[6], board[7], board[8]))

2.进行询问:是x先走还是o先走

3.人机进行交互落子

AI寻求落子算法

首要目的是要确保AI的每一步都不能出错,一出错可能就满盘皆输

  •  AI判定某个位置可以赢那么就选择这个位置落子
  •  否则,AI进行判定如果玩家下一步落某个位置赢,那么AI不让他赢,就落子落在这个位   置
  •  否则,按照中心,角,边的位置进行落子

这样就可以让AI立于不败之地了。

AI先找到可以落子的位置

def _moves(board):
    #寻求可落子的位置
    moves = []
    for i in range(9):
        if board[i] in list("012345678"):    #遍历了棋盘的位置如果位置为0-8那么这个位置可以落子
            moves.append(i)
    return moves

询问玩家落子位置,无效落子重复询问

def playermove(board):
    #询问并确定玩家的选择落子位置,无效落子重复询问
    move = 9
    while move not in _moves(board):
        move = int(input("请选择落子位置(0-8):"))
    return move

参数:棋盘,AI棋子,玩家棋子

并且运用winner函数,赢就返回True 

def computermove(board,computerletter,playerletter):
    #核心算法:计算AI的落子位置
    boardcopy = board.copy()

    #规则一:判断如果某位置落子可以获胜,则选择这个位置
    for move in _moves(boardcopy):
        boardcopy[move] = computerletter
        if winner(boardcopy):
            return move
        boardcopy[move] = str(move)

    #规则二:某个位置玩家下一步落子就可以获胜,则选择该位置
    for move in _moves(boardcopy):
        boardcopy[move] = playerletter
        if winner(boardcopy):
            return move
        boardcopy[move] = str(move)

    #规则三:按照中心、角、边的选择空的位置
    for move in(4,0,2,6,8,1,3,5,7):
        if move in _moves(board):
            return move

winner函数:判断怎样是获胜

分为八种情况,三种横线,三种竖线,两种对角线

def winner(board):
    #判断所给棋子是否获胜
    _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 _to_win:
        if board[r[0]] == board[r[1]] == board[r[2]]:
            return True
    return False

Tie函数:还有判定平局的情况 

def Tie(board):
    #判断是否平局
    for i in list("012345678"):
        if i in board:
            return False
    return True

完整代码实现

# python菜鸟
# 2022.01.10
def dis_board(board):
    #显示出棋盘
    print("\t{0} | {1} | {2}".format(board[0], board[1], board[2]))
    print("\t_ | _ | _")
    print("\t{0} | {1} | {2}".format(board[3], board[4], board[5]))
    print("\t_ | _ | _")
    print("\t{0} | {1} | {2}".format(board[6], board[7], board[8]))


def _moves(board):
    #寻求可落子的位置
    moves = []
    for i in range(9):
        if board[i] in list("012345678"):       #遍历了棋盘的位置如果位置为0-8那么这个位置可以落子
            moves.append(i)
    return moves

def playermove(board):
    #询问并确定玩家的选择落子位置,无效落子重复询问
    move = 9
    while move not in _moves(board):
        move = int(input("请选择落子位置(0-8):"))
    return move

def computermove(board,computerletter,playerletter):
    #核心算法:计算AI的落子位置
    boardcopy = board.copy()

    #规则一:判断如果某位置落子可以获胜,则选择这个位置
    for move in _moves(boardcopy):
        boardcopy[move] = computerletter
        if winner(boardcopy):
            return move
        boardcopy[move] = str(move)

    #规则二:某个位置玩家下一步落子就可以获胜,则选择该位置
    for move in _moves(boardcopy):
        boardcopy[move] = playerletter
        if winner(boardcopy):
            return move
        boardcopy[move] = str(move)

    #规则三:按照中心、角、边的选择空的位置
    for move in(4,0,2,6,8,1,3,5,7):
        if move in _moves(board):
            return move

def winner(board):
    #判断所给棋子是否获胜
    _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 _to_win:
        if board[r[0]] == board[r[1]] == board[r[2]]:
            return True
    return False

def Tie(board):
    #判断是否平局
    for i in list("012345678"):
        if i in board:
            return False
    return True

def tic_tac_toe():
    #井字棋
    board = list("012345678")
    playerletter = input("请选择棋子x(玩家)或者o(AI)——(x先走,o后走):")
    if playerletter in("X","x"):
        turn = "player"
        playerletter = "x"
        computerletter = "o"
    else:
        turn = "AI"
        computerletter = "x"
        playerletter = "o"
    print("{}先走!".format(turn))

    while True:
        dis_board(board)
        if turn == 'player':
            move = playermove(board)
            board[move] = playerletter
            if winner(board):
                dis_board(board)
                print("恭喜玩家获胜!")
                break
            else:
                turn = "AI"
        else:
            move = computermove(board, computerletter, playerletter)
            print("人工智能AI落子位置:",move)
            board[move] = computerletter
            if winner(board):
                dis_board(board)
                print("人工智能AI获胜!")
                break
            else:
                turn = "player"
        if Tie(board):
            dis_board(board)
            print('平局!')
            break


if __name__=='__main__':
        tic_tac_toe()


其中一个实现效果 

请选择棋子x(玩家)或者o(AI)——(x先走,o后走):x
player先走!
	0 | 1 | 2
	_ | _ | _
	3 | 4 | 5
	_ | _ | _
	6 | 7 | 8
请选择落子位置(0-8):8
	0 | 1 | 2
	_ | _ | _
	3 | 4 | 5
	_ | _ | _
	6 | 7 | x
人工智能AI落子位置: 4
	0 | 1 | 2
	_ | _ | _
	3 | o | 5
	_ | _ | _
	6 | 7 | x
请选择落子位置(0-8):2
	0 | 1 | x
	_ | _ | _
	3 | o | 5
	_ | _ | _
	6 | 7 | x
人工智能AI落子位置: 5
	0 | 1 | x
	_ | _ | _
	3 | o | o
	_ | _ | _
	6 | 7 | x
请选择落子位置(0-8):3
	0 | 1 | x
	_ | _ | _
	x | o | o
	_ | _ | _
	6 | 7 | x
人工智能AI落子位置: 0
	o | 1 | x
	_ | _ | _
	x | o | o
	_ | _ | _
	6 | 7 | x
请选择落子位置(0-8):7
	o | 1 | x
	_ | _ | _
	x | o | o
	_ | _ | _
	6 | x | x
人工智能AI落子位置: 6
	o | 1 | x
	_ | _ | _
	x | o | o
	_ | _ | _
	o | x | x
请选择落子位置(0-8):1
	o | x | x
	_ | _ | _
	x | o | o
	_ | _ | _
	o | x | x
平局!

进程已结束,退出代码0

遇到的一些问题

  • 缩进问题:python中是有着严格的缩进的,一旦缩进不规整,就会出现逻辑上的错误
  •  其他都是码代码的小问题,符号的错误,语言的错误,等等,需要后期认真纠正

Logo

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

更多推荐