#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 .