【问题标题】:checkDraw function for Tic Tac Toe - python井字游戏的 checkDraw 函数 - python
【发布时间】:2020-08-13 00:54:50
【问题描述】:

我编写了一个可以运行的井字游戏程序,但我一直在思考如何编写 chekDraw 函数(检查游戏是否平局)。所有其他功能都在工作,我可以玩游戏。我的想法是,for in range 循环将遍历棋盘索引,计算 x 和 o,直到整个棋盘都满了。总的来说,我的条件是,如果它不是胜利(checkWin),那么它就是平局。我已经盯着这个看了这么久,我希望对我的代码有新的看法。任何见解/建议将不胜感激!

编辑:特别是 checkDraw 发生的事情是什么 - 如果棋盘已满且没有赢家,游戏会不断要求移动,但此时任何移动都是非法的,因为所有位置都已被占用(来自 getMove 函数的验证) .

# display instructions
def displayInstructions():
    print()
    print("This is a game of Tic-Tac-Toe. You will select an empty location")
    print("and enter its index to select a move. The first player will be X")
    print("and the second player will be O.")
    print()


# display current state
# pass in board
# does not return anything
def showBoard(board):
    for i in range(len(board)):
        print("[" + str(board[i]) + "]", end="")
        if i == 2 or i == 5 or i == 8:
            print(end="\n")


# pass in board
# return updated board
# must validate move (in range, unoccupied square)
def getMove(board, player):
    validMove = False
    while not validMove:
        move = input("{0}, what is your move: ".format(player))
        position = int(move) - 1  # cast input as an integer, and puts player move in correct index
        # in range
        if position < 0 or position > 8:
            print("That is an illegal move.")
        # unoccupied square
        if board[position] == "X" or board[position] == "O":
            print("That is an illegal move.")
        else:
            # if valid move, put player on board
            board[position] = player
            return board


def checkWin(board, player):
    if (board[0] == player and board[1] == player and board[2] == player) or \
            (board[3] == player and board[4] == player and board[5] == player) or \
            (board[6] == player and board[7] == player and board[8] == player) or \
            (board[0] == player and board[3] == player and board[6] == player) or \
            (board[1] == player and board[4] == player and board[7] == player) or \
            (board[2] == player and board[5] == player and board[8] == player) or \
            (board[0] == player and board[4] == player and board[8] == player) or \
            (board[2] == player and board[4] == player and board[6] == player):
        return True
    else:
        return False


def checkDraw(board, player):
    count = 0
    for i in range(len(board)):
        if board[i] == player:
            # if board[i] == "X" or board[i) == "O"
            count += 1
        if count == len(board):
            return True


def main():
    # Repeat play loop
    playGame = True
    while playGame:
        # output instructions
        displayInstructions()
        # initialize board
        board = [1, 2, 3, 4, 5, 6, 7, 8, 9]
        print(len(board))
        # initialize first player to X
        player = "X"
        # play until win or draw
        while not checkWin(board, player) or checkDraw(board, player):
            showBoard(board)
            getMove(board, player)
            checkWin(board, player)
            checkDraw(board, player)
            # if the game is in play (not a win or draw)
            if not checkWin(board, player) or checkDraw(board, player):
                # swap player
                if player == "X":
                    player = "O"
                else:
                    player = "X"
        # if win
        if checkWin(board, player):
            showBoard(board)
            print("{0} wins.".format(player))
            playGame = False
        # if draw
        elif checkDraw(board, player):
            showBoard(board)
            print("It's a draw")
            playGame = False
        # Ask if want to play another game
        playAgain = input("Would you like to play again? (y/n): ").lower()
        if playAgain == "y":
            main()
        else:
            print("Goodbye.")


if __name__ == "__main__":
    main()

【问题讨论】:

  • 您在尝试实现 chekDraw 功能时遇到了哪些具体问题?
  • 我的建议是记录棋盘上有多少个 X/O,如果没有人赢,有 9 个棋子,那就是平局
  • 我建议将板子初始化为 ~None~ 的列表。然后,当您检查棋盘时,您可以说~for I in board: if i is None: return False~ 然后当您检查有效动作时,您可以确保该点尚未使用!
  • 感谢您的建议!我会试试看。

标签: python tic-tac-toe


【解决方案1】:

您应该构建一个形成段(线)的棋盘位置列表,而不是这些长系列的和/或,并将其用作间接获取棋盘上的所有模式:

例如:

segments = [ (0,1,2),(3,4,5),(6,7,8),(0,3,6),(1,4,7),(2,5,8),(0,4,8),(2,4,6) ]

boardMarks = [ c if c in "XO" else "." for c in board ]
patterns   = [ "".join(sorted(boardMarks[i] for i in s)) for s in segments ]

playerWins = (player*3) in patterns
xWins      = "XXX" in patterns
oWins      = "OOO" in patterns
draw       = not xWins and not oWins and "." not in boardMarks

或者,如果您想更有预测性并在没有更多可以获胜的动作时尽早宣布平局:

draw = not any(canWin in patterns for canWin in ("...","..X","..O",".XX",".OO"))

因为模式是排序的,所以只有 5 种组合代表一个可赢线

如果你想让电脑玩,你可以使用这个“自动播放”功能来选择一个基于 mini-max 评分系统的位置:

skill = 4 # 1 to 4 (novice to master)
def rating(position,player,board,level=skill+5):
    if board[position] in "XO" or not level: return 0
    newBoard = board[:position]+[player]+board[position+1:]
    isWin = player*3 in ( "".join(newBoard[i] for i in s) for s in segments )
    if isWin: return 3**level * 2
    nextRatings = [rating(p,"XO"[player=="X"],newBoard,level-1) for p in range(9)]
    return 3**level - max(nextRatings,key=abs)

from random import sample
def autoPlay(board,player):
    return max(sample(range(9),9),key=lambda p:rating(p,player,board))

使用示例:

position = autoPlay(board,player)
print("computer plays ",player," at position ",position+1)
board[position] = player

【讨论】:

    猜你喜欢
    • 2014-04-12
    • 1970-01-01
    • 1970-01-01
    • 2020-04-11
    • 2017-09-18
    • 2013-12-21
    • 2018-04-19
    • 2015-06-14
    相关资源
    最近更新 更多