Python класс, возвращающий старое значение атрибута - PullRequest
0 голосов
/ 12 июля 2020

У меня есть основной класс, второй класс, который обрабатывает получение сетки судоку (2D-массив), и третий класс, который решает головоломку и должен возвращать завершенную головоломку. Когда я запускаю программу, метод решения работает нормально и распечатывает решенную головоломку. Однако, когда я вызываю SudokuSolver.get_grid() из другого класса, возвращается исходная нерешенная сетка, переданная в SudokuSolver. Кроме того, когда я пытался вернуть self.grid из метода solve(), он всегда возвращал [[None]].

Вот мой класс решателя:

import numpy as np


class SudokuSolver:

    def __init__(self, in_grid):
        self.grid = in_grid

    def get_grid(self):
        return self.grid

    def solve(self):

        for y in range(9):
            for x in range(9):
                if self.grid[y][x] == 0:
                    for n in range(1, 10):
                        if self.possible(y, x, n):
                            self.grid[y][x] = n
                            self.solve()
                            self.grid[y][x] = 0
                    return
        print('Solved')
        print(np.matrix(self.grid))

    def possible(self, y, x, n):

        for i in range(0, 9):
            if self.grid[y][i] == n:
                return False
        for i in range(0, 9):
            if self.grid[i][x] == n:
                return False

        x0 = (x//3) * 3
        y0 = (y//3) * 3

        for i in range(0, 3):
            for j in range(0, 3):
                if self.grid[y0 + i][x0 + j] == n:
                    return False

        return True

Второй класс:

solver = SudokuSolver(self.get_grid())
solver.solve()
completed = solver.get_grid()
print('Completed')
print(np.matrix(completed))

Почему SudokuSolver возвращает старое значение сетки, которое было передано, а не завершенное значение, напечатанное в конце метода solve()?

Ответы [ 2 ]

0 голосов
/ 12 июля 2020

Эта строка:

self.grid[y][x] = 0

постоянно вызывается после того, как решение завершено. Для проверки поместите любое выражение print непосредственно перед или после него. Вы увидите, что его вывод появится как до, так и после вывода «Решено».

Я плохо разбираюсь в теории судоку, но это простое исправление сработало для меня. Инициализируйте атрибут solved в инициализаторе:

self.solved = False

Когда вы знаете, что закончили, установите для него значение True:

print('Solved')
print(np.matrix(self.grid))
self.solved = True

И затем вложите код обнуления в условное:

if not self.solved:
    self.grid[y][x] = 0

Теперь эта команда будет пропущена, если ваша головоломка уже решена. Может быть более элегантный способ реализации алгоритма, но это исправляет функциональность вашего кода.

(Обратите внимание, что, как указано в ответе Яна Уилсона, в вашем текущем коде solver.grid и содержащий класс self.grid - это одно и то же, поэтому решатель активно изменяет исходную сетку, предоставленную ему. Это может быть, а может и не быть тем, что вы намеревались.)

0 голосов
/ 12 июля 2020

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

import copy

class OtherClass():

    def start_solver(self):
        grid_copy = copy.deepcopy(self.get_grid())
        solver = SudokuSolver(grid_copy)
        #...

Поскольку у вас есть список списков, вы должны использовать глубокую копию. Если бы это был просто одноуровневый список, вы могли бы использовать grid.copy() или grid[:] для создания неглубокой копии.

Было бы неплохо переместить операцию копирования в конструктор решателя или в get_grid().

глубокая копия

передать по ссылке

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...