Как я могу использовать меньше циклов for в этой игре и быть более эффективным и динамичным с меньшим количеством линейных кодов?

#python #function #for-loop #nested-lists #tic-tac-toe

#python #функция #for-цикл #вложенные списки #крестики-нолики

Вопрос:

 def tic_tac_toe(board):

    mess = []   
    organize = []     
    winner = []   
    n = len(board)
 

Могу ли я сделать это без такого количества циклов for?

     for i in range(len(board)):
        for j in range(len(board[i])):
            mess.append(board[j][i]) 
     #appending all vertical items


    for i in range(len(board)):
        for j in range(len(board[i])):
            mess.append(board[i][j]) 
    #appending all horizontal items


    for i in range(len(board)):
        for j in range(len(board[i])):
            i = j
            mess.append(board[i][j])
        break

    #appending items that have the same i and j index (i==0 j==0,i==1 j==1,i==2 j ==2) or better say all items in these position ()


    for i in range(len(board)):
        for j in range(len(board[i])):
            if j - i == 2 or i - j == 2 or (i == 1 and j == 1):
                mess.append(board[i][j])  
    #appending items in these indexes : (i ==0 j ==2 , i == 1 j == 1, i ==2 j == 0) items in these position (/) 



    organize = [mess[k: k   n] for k in range(0, len(mess), n)] # creating nested list of all possible moves


    winner = ["X" if organize[i].count("X") == 3 else "O" if organize[i].count("O") == 3 else "Draw" for i in range(len(organize))] # "X" if 3 "X"s in organize[i]. "O" if 3 "O"s in organize[i] and "Draw" otherwise .
 

и это определяет победителя. если один единственный «X» в списке победителей, победителем становится «X» . То же самое для «O». но если все элементы в списке победителей были «Ничья», игра является ничьей.

сильный текст

     if "X" in winner:
        return "X"
    elif "O" in winner:
        return "O"
    elif winner.count("Draw") == 8 :
        return "Draw"  

   

print(tic_tac_toe([
    ["X", "X", "O"],
    ["O", "O", "X"],
    ["X", "X", "O"]
])) # ➞ "Draw"
 

Комментарии:

1. Может быть, попробуйте list comprehensions для заполнения ваших списков

2. @IoaTzimas Я пытался, но потерпел неудачу. Четвертый цикл for превосходит мои знания.

3. Одна небольшая вещь, для вашего третьего цикла for, вы могли бы просто использовать внешний цикл с mess.append(board[i][i])

4. Делайте отношения. Столбцы, строки и диагонали указывают на три X (или O) с индексом 1 друг от друга, или три последовательных 4, или три последовательных 2, где одна из плиток #6). Вы можете проверить это с помощью одного вложенного цикла с тремя условиями в нем

Ответ №1:

Если вы с удовольствием делаете это с помощью numpy, вы можете значительно упростить его. Numpy позволяет поворачивать доску, что означает, что вы можете находить горизонтальные линии с тем же кодом, что и вертикальные линии (и то же самое касается двух диагоналей).

 import numpy as np

organize = []

board_rotated = np.rot90(board).tolist() # rotate the board

organize.extend(board) # add horiztonal
organize.extend(board_rotated) # add vertical
organize.append(np.diag(board).tolist()) # add top-left to bottom-right diagonal
organize.append(np.diag(board_rotated).tolist()) # add top-right to bottom-left diagonal
 

Это можно сделать вообще без циклов for, плюс вам не нужно иметь mess список. Все добавляется непосредственно в organize .


Происходит поворот доски, что позволяет вам выполнять те же операции на повернутой доске, что и на не повернутой доске, чтобы получить все решения. В примере, приведенном в вопросе, board_rotated будет:

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

Как и ожидалось, это было повернуто на 90 градусов.
Вызовы .extend() функций просто добавляют каждую строку в organise . В случае board строк — это горизонтальные значения. Строки — это вертикальные значения при использовании board_rotated .
Использование np.diag() дает вам диагональ матрицы. Для board этого есть ['X', 'O', 'O'] и для board_rotated этого есть ['O', 'O', 'X'] .

Ответ №2:

Для циклов for вы можете легко написать 1 цикл вместо 2:

вместо:

 for i in range(len(board)):
    for j in range(len(board[i])):
        mess.append(board[j][i])
 

вы можете написать:

 for i, j in enumerate(board):
    mess.append(board[j][i])
 

и, конечно, это относится и к другим циклам for .

Однако вы также можете написать функцию для уменьшения количества циклов for .