Как можно уменьшить/объединить этот код C#(Unity)?
public void priceBoost(int numPrice)
{
if **(numPrice == 1 && GameManager.banana >= 1000 && GameManager.banana <= 5000)**
{
GameManager.price1 += 10;
GameManager.buy1 += 10;
PlayerPrefs.SetInt("buy1", GameManager.buy1);
PlayerPrefs.SetInt("price1", GameManager.price1);
}
**if (numPrice == 1 && GameManager.banana >= 10000 && GameManager.banana <= 50000)**
{
GameManager.price1 += 100;
GameManager.buy1 += 100;
PlayerPrefs.SetInt("buy1", GameManager.buy1);
PlayerPrefs.SetInt("price1", GameManager.price1);
}
}
Как можно объединить выделенные(находящиеся в между * звездочками) строчки кода?
Ответы (2 шт):
Можно "упростить" условия и вынести общие части:
public void priceBoost(int numPrice) {
if (numPrice == 1 && GameManager.banana >= 1000) {
int boost = 0;
if (GameManager.banana <= 5000) {
boost = 10;
} else if (GameManager.banana >= 10000 && GameManager.banana <= 50000) {
boost = 100;
}
GameManager.price1 += boost;
GameManager.buy1 += boost;
PlayerPrefs.SetInt("buy1", GameManager.buy1);
PlayerPrefs.SetInt("price1", GameManager.price1);
}
}
Сокращение и упрощение в программирование как путание теплого с мягким. Их можно не объединять а вовсе выделить в правило, которое само может проверить данные на её соответствие требованиям:
_rules = new[]
{
new Rule(1, 1000, 5000, new Values(10, 10)),
new Rule(1, 10000, 50000, new Values(100, 100)),
};
foreach (var rule in _rules)
if (rule.IsConformity(level, value))
{
_values = rule.values; // buy1 и price1
break;
}
После чего добавление новых условий будет занимать всего одну строчку, можно легко написать хоть десятки и никакой вереницы if else вообще не будет!
Но для этого нужно учиться декомпозиции задачи на простые элементы и описывать каждый элемент одним классом с одной единственной ответственностью. В результате этого кода якобы больше, но при расширении его по факту меньше и он не посыпится.
Твой пока-что маленький кусочек кода, который намеривается стать пизанской башней одновременно апгрейд, баланс, сохранитель и что только не. numPrice это какой-то уровень апгрейда, насколько я понял, и если price1 и buy1 жестко зависят от numPrice и banana то зачем ты сохраняешь первых, а не вторых высчитывая их из первых? Мне кажется что price1 и buy1 в принципе существуют в связке и нет смысла их разделять. Стоит написать сущность типа Upgrade, которая сама следит за своим состоянием. Правило само по себе сущность, как упомянуть выше. И кто-то кто связывает все во едино.
public struct TradePrice
{
public int buy;
public int sell;
public TradePrice (int buy, int sell)
{
this.buy = buy;
this.sell = sell;
}
}
public struct PriceRequire
{
public int requireLevel;
public int minValue;
public int maxValue;
public PriceRequire (int requireLevel, int minValue, int maxValue)
{
this.requireLevel = requireLevel;
this.minValue = minValue;
this.maxValue = maxValue;
}
public bool IsConformity (int level, int value)
{
return requireLevel == level && value >= minValue && value < maxValue;
}
}
public class Economic
{
private readonly Dictionary<PriceRequire, TradePrice> _prices; // справочник правил и цен
private readonly Upgrade _tradeStat; // откуда берем уровень
private readonly Func<int> _targetValue; // метод возвращающий значение числа (banana)
private TradePrice _defaultPrice = new TradePrice(1, 1);
private TradePrice _currentPrice; // buy и price в связке
public Economic (Func<int> targetValue)
{
_targetValue = targetValue;
_tradeStat = new Upgrade("Trade", 1);
_prices = new Dictionary<PriceRequire, TradePrice>();
_prices.Add(new PriceRequire(1, 0, 1000), new TradePrice(1, 1));
_prices.Add(new PriceRequire(1, 1000, 5000), new TradePrice(10, 10));
_prices.Add(new PriceRequire(1, 5000, 10000), new TradePrice(50, 50));
_prices.Add(new PriceRequire(1, 10000, 50000), new TradePrice(100, 100));
UpdatePrice();
}
public TradePrice Price => _currentPrice;
public void LevelUp ()
{
_tradeStat.LevelUp();
UpdatePrice();
}
public void UpdatePrice ()
{
foreach (var price in _prices)
if (price.Key.IsConformity(_tradeStat.Level, _targetValue()))
{
_currentPrice = price.Value;
return; // вместо break завершаем сам метод, а не цикл
}
_currentPrice = _defaultPrice; // если в справочнике не оказалось подходящих совпадений
}
}
Остается только написать Upgrade который принимает ключ для PlayerPrefs, базовый уровень и может сам загружает и сохранять свой уровень. Можно прописывать бесчисленное количество правил, изменять условия с бананов на персики не переписывая фигалион строк кода и в принципе модифицируя конструкцию.
Не думаю что это поможет прямо сейчас, но как ориентир. Думаю что взглянув на пример, удобство дольнейшей работы с таким кодом очевидны даже начинающему. Не бойся писать плохо или даже ужасно, пиши больше что-бы лучше чувствовать в каких местах болит после написанного и появляется желание уметь это лечить.
п.с. GameManager это безликая сущность не имеющая смысла, она как мем и не должна существовать. GameManager.banana... хм банан... GameManager это мартышка или склад?... GameManager.price цены! видимо все-таки склад... GameManager.buy покупка? походу биржа $#? А у тебя этих полей не связанных между собой там много и не только поля.