Я хотел бы знать, есть ли способ автоматически обновлять значение в словаре на основе изменений, внесенных в значения в другом словаре. У меня есть 2 словаря следующим образом:
enum CharacterAttributes: String, Codable {
case strength
case constitution
case dexterity
case intelligence
}
enum CharacterStats: String, Codable {
case maxHealthPoint
case maxTacticPoint
case maxActionPoint
case movementSpeed
}
var attributes = [CharacterAttributes: Float]()
var stats = [CharacterStats: Float]()
Логика такова:
stats[.maxHealthPoint] = attributes[.constitution] * 100
stats[.maxTacticPoint] = (attributes[.dexterity] + attributes[.intelligence]) * 1.5
stats[.maxActionPoint] = attributes[.constitution] * 10
stats[.movementSpeed] = attributes[.dexterity] + 70
Чего я хочу добиться, так это того, что всякий раз, когда значение изменяется из словаря атрибутов, соответствующие значения в статистике обновляются автоматически. Я знаю, что для обычной переменной я могу использовать ключевое слово DidSet, но как применить эту концепцию к словарям?
Заранее благодарю за любую помощь.
Да, статистика зависит от атрибутов, а не наоборот. однако определенное значение в статистике должно быть разрешено изменять напрямую. например stats[.movementSpeed] = 100
Кажется, я что-то пропустил. Почему didSet
не работает как решение? — И зачем именно эти словари? Разве структура не была бы проще?
Хорошо, если некоторую статистику можно установить, то когда эта статистика должна «синхронизироваться» с атрибутами? Когда stats[.movementSpeed]
вернется к attributes[.dexterity] + 70
после того, как вы установили значение 100?
Извините, правильный способ изменения скорости должен выглядеть так: stats[.movementSpeed] += someModifier. Таким образом, при изменении атрибутов[.dexterity] статистика[.movementSpeed] всегда должна оставаться синхронизированной. Кажется, Саш дал мне нужный ответ. Спасибо, в любом случае.
Вы уверены, что словари — правильный способ хранения этой информации? Некоторые структуры с наблюдателями didSet
сделают это очень легко.
Попробуйте использовать наблюдатель DidSet после инкапсуляции словарей в класс:
import Foundation
enum CharacterAttributes: String, Codable {
case strength
case constitution
case dexterity
case intelligence
}
enum CharacterStats: String, Codable {
case maxHealthPoint
case maxTacticPoint
case maxActionPoint
case movementSpeed
}
class Character {
private var _attributes = [CharacterAttributes: Float]() {
didSet {
updateStats()
}
}
private var _stats = [CharacterStats: Float]()
var attributes: [CharacterAttributes: Float] {
get { _attributes }
set {
_attributes = newValue
updateStats()
}
}
var stats: [CharacterStats: Float] {
get { _stats }
set {
_stats = newValue
}
}
init(attributes: [CharacterAttributes: Float]) {
self._attributes = attributes
updateStats()
}
private func updateStats() {
_stats[.maxHealthPoint] = (_attributes[.constitution] ?? 0) * 100
_stats[.maxTacticPoint] = ((_attributes[.dexterity] ?? 0) + (_attributes[.intelligence] ?? 0)) * 1.5
_stats[.maxActionPoint] = (_attributes[.constitution] ?? 0) * 10
if _stats[.movementSpeed] == nil { // Allow manual setting
_stats[.movementSpeed] = (_attributes[.dexterity] ?? 0) + 70
}
}
}
Пример использования:
var character = Character(attributes: [.constitution: 5, .dexterity: 3, .intelligence: 2])
print(character.stats)
character.attributes[.constitution] = 7
character.stats[.movementSpeed] = 100
character.attributes[.dexterity] = 4
print(character.stats)
Выход:
[SwiftPlayground.CharacterStats.maxHealthPoint: 500.0, SwiftPlayground.CharacterStats.maxTacticPoint: 7.5, SwiftPlayground.CharacterStats.maxActionPoint: 50.0, SwiftPlayground.CharacterStats.movementSpeed: 73.0]
[SwiftPlayground.CharacterStats.maxHealthPoint: 700.0, SwiftPlayground.CharacterStats.maxTacticPoint: 9.0, SwiftPlayground.CharacterStats.maxActionPoint: 70.0, SwiftPlayground.CharacterStats.movementSpeed: 100.0]
Это круто! Это именно то, что я искал. Спасибо.
Значит,
stats
должно зависеть отattributes
, а не наоборот, верно? Можно ли изменитьstats
напрямую? Можно ли делатьstats[.maxHealthPoint] = 100
например?