【问题标题】:Appending integers to an empty list, then printing those integers (Tic-Tac-Toe)将整数附加到空列表,然后打印这些整数(井字游戏)
【发布时间】:2021-06-27 22:57:20
【问题描述】:

我对 Python 很陌生(上个月开始学习 Udemy 课程,然后编写了我的第一行 Python 代码),所以我希望有人可以就某个方面提供仁慈的建议我正在开发的交互式井字游戏项目。注意:这是一个两人游戏,其中两个玩家将使用同一台计算机。

问题:

我正在尝试编写一个函数,该函数将接收 1-9 范围内的用户输入(“位置”),将该输入作为整数存储在一个名为“板”的空列表中,然后将位置替换为称为“标记”的变量(“X”或“O”)。

我的代码:

# POSITION IS SUPPOSED TO BE AN INT THAT IS STORED IN A LIST CALLED "BOARD"

board = [''] * 9
marker = ''
position = ''

def place_marker(board, marker, position):


# while our position is an acceptable value
    while position not in range(1,9+1):
        position = int(input("Choose a number from 1 through 9: " ))   
        board.append(position)

    print(board)

# NOW HOW DO I MAKE SURE THAT THE POSITION CORRESPONDS WITH EACH MARKER?

解决方案尝试失败:

我有点忘记了我失败的解决方案尝试,但这里是其中之一:

board = [''] * 9
marker = ''
position = ''

def place_marker(board, marker, position):


# while our position is an acceptable value
    while position not in range(1,9+1):
        position = int(input("Choose a number from 1 through 9: " ))   
        board.append(position)

# at the board's position, place marker 'X' or 'O'
    board[position] = marker
    print(board)

这导致:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-197-76194c5efcbd> in <module>
----> 1 board[position]

TypeError: list indices must be integers or slices, not str

也许我一次尝试做太多事情。我尝试参考文档以及 W3Schools 和 Real Python 等其他资源,但我似乎无法为我的生活找出解决方案。如果有人能指出我的不足或出错的地方,或者在正确的方向上给我一两条线索,我将非常感激。

【问题讨论】:

  • board.append(position) 不应在 while 循环内。
  • 您不应该在board 上附加任何内容。
  • board 不是一个空列表,您填写的是:board = [''] * 9
  • position 不应该是函数参数,如果你在函数中分配它。
  • 列表索引从 0 开始,而不是 1。

标签: python list append tic-tac-toe


【解决方案1】:

我不确定我的答案是否正是你想要的,但你可以这样做:

board = ['']*9
marker = "X"
position=0

def place_marker(board, marker, position):


# while our position is an acceptable value
    while position not in range(1,9+1):
        position = int(input("Choose a number from 1 through 9: " ))   
        #board.append(position-1)

# at the board's position, place marker 'X' or 'O'
    board[position-1] = marker
    print(board)
    
place_marker(board, marker, 4)

位置应设置为整数。 board[] 的索引从 0 开始,所以你输入的位置应该 -1 表示 board[] 中的位置。

输出:

['', '', '', 'X', '', '', '', '', '']

【讨论】:

  • 谢谢@AustinHe。我非常感谢您的回复。无可否认,我花了一些时间来理解为什么这段代码有效,但这是我的理解:因为列表索引从 0 开始,我们必须从输入中 -1 以确保板只包含我们想要的实际值范围 1-9 .我会与其他评论者提出的观点一起考虑这一点,并自己再次解决这个问题。
【解决方案2】:

当您使用这样的游戏时,我建议将棋盘作为整数列表。这将使编码变得更加容易,并且您将在变量类型之间来回切换时犯更少的错误。要轻松切换转弯,您可以使用 -1 作为 X,1 作为 O,和 0 作为空格,这也将使检查空槽变得超级容易。

获取用户输入

board = [0]*9  # Init board
print_board(board)  # Print board at start of game
user_turn = True  # User goes first

# Game loop
while 1:

# User turn to move
    if user_turn:

        # Loop until we get a valid input from user
        while 1:

            # Get user input from the console
            user_input = input('\nPlease enter your move (1-9): ')

            # Check if user input is a number
            if user_input.isnumeric():

                # If it is a number, make the string is an integer and subtract 1 since array indices starts at 0
                user_input = int(user_input) - 1

                # Check if the input - 1 is in range 0-8
                if user_input in range(9):

                    # Check if the input is an empty square
                    if board[user_input] == 0:

                        # If all conditions are true: Make the move on the board, print the new board and change turn
                        board[user_input] = -1
                        print_board(board)
                        user_turn = not user_turn
                        break

打印白板

在这里,您可以将整数板转换为 X、O 和空白点。可以通过这个简短的函数来完成。

def print_board(board):
    temp_board = [' ' if i == 0 else 'X' if i == -1 else 'O' if i == 1 else i for i in board]
    for row in range(3):
        print(f'\n{temp_board [row*3:3+row*3]}' if row == 0 else temp_board [row*3:3+row*3])

您将其转换为字符串元素,然后将其打印在不同的行上。

查看获奖者和全食宿

您可以先定义所有获胜线:

winning_lines = ([0, 1, 2], [3, 4, 5], [6, 7, 8],  # Horizontally
             [0, 3, 6], [1, 4, 7], [2, 5, 8],  # Vertically
             [0, 4, 8], [2, 4, 6])  # Diagonally

然后您通过比较输入板和玩家轮次来检查是否获胜,看看它是否与获胜线匹配。

def is_winner(board, player):
    for pos in winning_lines:
        if board[pos[0]] == board[pos[1]] == board[pos[2]] == player:
            return 1

检查板是否已满更容易:

def is_board_full(board):
    return 0 if 0 in board else 1

结束 cmets

当您在游戏循环中切换回合时,您还需要检查胜利或棋盘是否已满,以查看是否应该结束循环,并可能要求玩家再次玩。您也可以在换回合后添加一个 AI 播放器,例如让它使用 Negamax 算法播放。

如果你想要完整的代码,你可以查看我的Tic-Tac-Toe repository。有多个版本,包括 Player vs Player (pvp) 和 Player vs Environment/AI (pve),您可以查看评论版本和压缩版本以获得一些灵感。如果您有任何问题,请告诉我:)

【讨论】:

  • 嗨@eligolf — 非常感谢您非常回答我的问题,并提供了如此详尽的分步示例!在我的 OP 几天后,我最终报废了原件并解决了问题into these smaller steps instead。但是,我仍然不知道如何编写/修改代码,以便用户只能在板上有空白区域时放置一个标记(这里用占位符“$”表示)。
  • 您在第一步中的方法(获取用户输入)非常简洁,但与其复制您所写的内容,我将看看是否可以使用自己的代码得出相同的结果并将您的代码用作资源/用于比较。如果您的代码中有一件事我不明白,那就是 Python 如何接受“while 1”作为游戏循环和“while 1”作为用户输入循环。你能再解释一下吗?顺便说一句,非常感谢您包含您的井字游戏存储库!很酷。 @eligolf
  • 在我的第一个输入部分的代码 cmets 中,您可以看到如何控制用户只放置在空方格上。在您发送的图像中,您似乎正在尝试同时让用户 1 和用户 2 输入而不将标记放在板上,为什么?您需要获取用户 1 的输入,检查其是否有效,如果是,则将其放在板上,然后为用户 2 更改轮次并重复。
  • while 1 在 Python 中只是意味着循环将继续直到你中断。为清楚起见,您可以为第一个循环分配一个 bool while_playing,为第二个循环分配一个 while_user_1,然后在您想要中断时将这些 bool 更改为 False。结果是一样的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多