Разбор задачи: Игра в жизнь

Предложенный нами код решения:

 def gameOfLife(board):
        m, n = len(board), len(board[0])
        matrix = [[0] * n for i in range(m)]
        for i in range(m):
            for j in range(n):
                cnt = 0
                for x, y in ((i - 1, j), (i + 1, j), (i, j - 1), (i, j + 1), (i - 1, j - 1), (i + 1, j + 1), (i - 1, j + 1), (i + 1, j - 1)):
                    if 0 <= x < m and 0 <= y < n and board[x][y] == 1: cnt += 1
                if (board[i][j] and 2 <= cnt <= 3) or (not board[i][j] and cnt == 3): matrix[i][j] = 1
        for i in range(m):
            for j in range(n):
                board[i][j] = matrix[i][j]

Решение основано на прямом применении правил игры "Жизнь" для каждого элемента матрицы. Давайте разберем его шаг за шагом.


1. Инициализация переменных

m, n = len(board), len(board[0])
matrix = [[0] * n for i in range(m)]
  • Здесь определяется размер матрицы m (число строк) и n (число столбцов).
  • Создается новая матрица matrix такого же размера, заполненная нулями. Эта матрица будет использоваться для хранения следующего состояния игры.
    Пример: Если board = [[1, 0], [0, 1]], то matrix = [[0, 0], [0, 0]].

2. Итерация по всем клеткам матрицы

for i in range(m):
    for j in range(n):
        cnt = 0
  • Вложенный цикл проходит по каждой клетке исходной матрицы board. Переменные i и j представляют координаты текущей клетки.
  • Переменная cnt инициализируется как 0. Она будет использоваться для подсчета числа живых соседей текущей клетки.

3. Подсчет живых соседей

for x, y in ((i - 1, j), (i + 1, j), (i, j - 1), (i, j + 1), (i - 1, j - 1), (i + 1, j + 1), (i - 1, j + 1), (i + 1, j - 1)):
    if 0 <= x < m and 0 <= y < n and board[x][y] == 1: 
        cnt += 1
  • Здесь проверяются все 8 соседей текущей клетки (i, j).
    Направления:
    • (i - 1, j) — клетка сверху.
    • (i + 1, j) — клетка снизу.
    • (i, j - 1) — клетка слева.
    • (i, j + 1) — клетка справа.
    • (i - 1, j - 1) — диагональ сверху-слева.
    • (i + 1, j + 1) — диагональ снизу-справа.
    • (i - 1, j + 1) — диагональ сверху-справа.
    • (i + 1, j - 1) — диагональ снизу-слева.
  • Для каждой соседней клетки (x, y) выполняется проверка:

    • Она должна находиться в пределах границ матрицы: 0 <= x < m и 0 <= y < n.
    • Она должна быть живой: board[x][y] == 1.

    Если обе проверки пройдены, счетчик cnt увеличивается на 1.

Пример:
Для клетки (1, 1) в матрице:

board = [
    [1, 0, 1],
    [0, 1, 0],
    [1, 0, 1]
]

Соседи: (0, 1), (2, 1), (1, 0), (1, 2), (0, 0), (0, 2), (2, 0), (2, 2).
Живые соседи: (0, 0), (0, 2), (2, 0), (2, 2)cnt = 4.


4. Применение правил игры

if (board[i][j] and 2 <= cnt <= 3) or (not board[i][j] and cnt == 3): 
    matrix[i][j] = 1
  • Если текущая клетка живая (board[i][j] == 1):
    • Она останется живой, если число живых соседей находится в диапазоне от 2 до 3 включительно: 2 <= cnt <= 3.
  • Если текущая клетка мертвая (board[i][j] == 0):
    • Она становится живой, если у нее ровно 3 живых соседа: cnt == 3.

Результат записывается в новую матрицу matrix.


5. Копирование нового состояния обратно

for i in range(m):
    for j in range(n):
        board[i][j] = matrix[i][j]
  • Новый массив matrix с обновленным состоянием копируется обратно в исходный массив board.

Пример работы

Исходная матрица:

board = [
    [0, 1, 0],
    [0, 0, 1],
    [1, 1, 1],
    [0, 0, 0]
]

Ход выполнения:

  1. Подсчет соседей и применение правил:
    • Клетка (0, 1) имеет 2 соседа → остается живой.
    • Клетка (1, 2) имеет 3 соседа → становится живой.
    • Клетка (2, 1) имеет 3 соседа → остается живой.
    • Другие клетки обновляются аналогично.

Промежуточная matrix:

matrix = [
    [0, 0, 0],
    [1, 0, 1],
    [0, 1, 1],
    [0, 1, 0]
]
  1. Копирование результата:
    • Исходный board обновляется значениями из matrix.

Результат:

board = [
    [0, 0, 0],
    [1, 0, 1],
    [0, 1, 1],
    [0, 1, 0]
]

 



Вы должны Войти или Зарегистрироваться чтобы оставлять комментарии