Я рассматриваю возможность сохранения координаты в самом объекте GridElement, но это также выглядит как плохой дизайн, потому что мне нужно будет постоянно обновлять его, когда GridElement меняет местоположение.
Я думаю, что-то вроде этого является жизнеспособным решением. Вместо того, чтобы хранить его внутри объекта элемента сетки, вы можете сохранить координаты в другом словаре:
private var gridElementPositionDict: [GridElement: Coord]
Как вы сказали, для этого потребуется постоянно устанавливать значения для gridElementPositionDict
всякий раз, когда элемент сетки меняет положение. Однако вы можете использовать некоторые инкапсуляции, чтобы установить их только в одном месте.
Сначала создайте массив elements
private
и добавьте subscript
, который принимает два параметра, в ваш класс Grid
. Подстрочный индекс примет Coord
для доступа к конкретному элементу сетки в определенной позиции. В установщике этого индекса вы можете изменить gridElementPositionDict
для установки новых позиций GridElement
.
Затем вы можете написать другой метод (или индекс), который принимает GridPosition
, который возвращает свою позицию.
Вы также можете добавить такие методы, как swapElements(at:and:)
, changeElementPositon(_:to:)
и т. Д. Все дело в инкапсуляции вашей структуры данных.
Вот пример кода:
class Grid<T: Hashable> {
private var elements: [[T?]]
private var elementsPositionDict: [T: Coord]
init() {
elements = [
[nil, nil, nil, nil],
[nil, nil, nil, nil],
[nil, nil, nil, nil],
[nil, nil, nil, nil],
]
elementsPositionDict = [:]
}
subscript(_ coord: Coord) -> T? {
get { return elements[coord.x][coord.y] }
set {
// this is the ONLY place you modify the dictionary
if let oldValue = elements[coord.x][coord.y] {
elementsPositionDict[oldValue] = nil
}
elements[coord.x][coord.y] = newValue
if let v = newValue {
elementsPositionDict[v] = coord
}
}
}
func coord(of element: T) -> Coord? {
return elementsPositionDict[element]
}
}