根据从数组中提取的值减少对象值?

gorkyyrv  于 2021-09-23  发布在  Java
关注(0)|答案(4)|浏览(399)

我正在用javascript构建一个空闲的游戏。
这是一个你经营面包店的游戏。
面包房的资源在对象“mainobj”中表示。

let mainObj = {
  "Money": 100,
  "Resources": {
    "Milk": 10,
    "Eggs": 10,
    "Flour": 10,
    "Water": 10,
    "Sugar": 10
  },
  "Employees": {
    "Bakers": 1,
    "Cooks": 0,
    "Servers": 0,
    "Farmers": 0
  },
  "Inventory": {
    "Cake": 0,
    "Cookies": 0
  }
}

烘焙项目(如蛋糕或饼干)的相关成本存储在数组“bakeinfo”中。

let bakeInfo = [{
  "Name": "Cake",
  "Milk": 1,
  "Eggs": 2,
  "Flour": 1
}, {
  "Name": "Cookies",
  "Eggs": 1,
  "Flour": 1
}]

我想写一个函数,从 bakeInfo ,例如用于烘焙蛋糕(1份牛奶、2份鸡蛋、1份面粉)检查 mainObj 对于所需的成分(如果不够,则抛出一个错误),如果每种成分都足够,则会将资源中的成分减少 bakeInfo ,然后将适当的项目(蛋糕/饼干)添加到 mainObj 库存
我尝试了几种不同的方法,几乎每种成分都有一个单独的功能,这对我来说效率非常低。
此外,一些将要烘焙的食物省略了一些成分(饼干不需要牛奶)。因此,如果函数选中此项/仅从 mainObj 这将是理想的库存,事实上,这是必要的。
如果有人能给我指出正确的方向那就太好了。

pn9klfpd

pn9klfpd1#

上面marko的解决方案是一次添加一个项目。但是,如果您希望一次检查多个项目,并且如果没有足够的成分容纳所有项目,则会出现错误,此解决方案可能会更好:

let mainObj = {
  Money: 100,
  Resources: {
      Milk: 10,
      Eggs: 10,
      Flour: 10,
      Water: 10,
      Sugar: 10
  },
  Employees: {
      Bakers: 1,
      Cooks: 0,
      Servers: 0,
      Farmers: 0
  },
  Inventory: {
      Cake: 0,
      Cookies: 0
  },
}

let bakeInfo = [
  {Name: 'Cake', Milk: 1, Eggs: 2, Flour: 1},
  {Name: 'Cookies', Eggs: 1, Flour: 1} 
]

function bakeOrError(bakeInfo, mainObj) {
  // first make a copy of resources
  const resources = Object.assign({}, mainObj.Resources); 
  // now, iterate over all the bakeInfo and reduce resources
  bakeInfo.forEach(bi => {
    Object.keys(bi)
      .filter(k => k !== 'Name') // don't operate on the Name key, everything else is an ingredient
      .forEach(k => {
        resources[k] -= bi[k];
        if (resources[k] < 0) throw new Error('insufficient resources');
      })
  })

  // if we haven't errored by here, there were enough ingredients to support everything.
  // update the resources object
  mainObj.Resources = resources;
  // then add to inventory
  bakeInfo.forEach(bi => mainObj.Inventory[bi.Name]++);
}

bakeOrError(bakeInfo, mainObj);
console.log(mainObj);
2skhul33

2skhul332#

这应该起作用:

function reduceResources(info){
  let bakeInfoKeys = Object.keys(info);

  // check if there is enough resources
  bakeInfoKeys.forEach(key => {
    if(mainObj.Resources[key] !== undefined){
        if(mainObj.Resources[key] < info[key])
            return false; // return false if there is not enough resources
    }
  });

  // reduce the resource amount
  bakeInfoKeys.forEach(key => {
    if(mainObj.Resources[key] !== undefined){
        mainObj.Resources[key] -= info[key];
    }
  });

  // add the item to the inventory
  mainObj.Inventory[info['Name']] += 1;

  return true;
}

如果函数成功,则返回true;如果资源不足,则返回false。
您可以这样使用它:

if(reduceResources(bakeInfo[0]))
    console.log("Success!")
else
    console.log("Fail!")
anauzrmj

anauzrmj3#

makeItem 在下面的函数中,您可以使用 try-catch 然后扔一个 Error 无法满足所需资源的最低数量时。

const player = {
  "Money": 100,
  "Resources": { "Milk": 10, "Eggs": 10, "Flour": 10, "Water": 10, "Sugar": 10 },
  "Employees": { "Bakers": 1, "Cooks": 0, "Servers": 0, "Farmers": 0 },
  "Inventory": { "Cake": 0, "Cookies": 0 }
};

const recipes = [
  { "Name": "Cake", "Milk": 1, "Eggs": 2, "Flour": 1 },
  { "Name": "Cookies", "Eggs": 1, "Flour": 1 }
];

const retrieveRecipe = (name) =>
  recipes.find(({ Name }) => Name === name);

const canMake = (player, recipe) => {
  const found = retrieveRecipe(recipe);
  if (found == null) return false;
  const { Name, ...ingredients } = found;
  const { Resources } = player;
  return Object.entries(ingredients)
    .every(([ name, amount ]) => amount <= Resources[name]);
}

const makeItem = (player, recipe) => {
  if (!canMake(player, recipe)) throw new Error('Insufficient resources');
  const found = retrieveRecipe(recipe);
  const { Name, ...ingredients } = found;
  Object.entries(ingredients).forEach(([name, amount]) => {
    player.Resources[name] -= amount;
  });
  player.Inventory[Name]++;
}

// Make cakes until required resources cannot be met.
try {
  while (true) {
    makeItem(player, 'Cake');
  }
} catch (e) {
  console.log('Ran out of resources!');
}

console.log(player);
.as-console-wrapper { top: 0; max-height: 100% !important; }
unhi4e5o

unhi4e5o4#

下面是我将如何着手的。

function Bakery(state, recipes) {
    this.state = state;
    this.recipes = recipes;

    this.bake = function (name) {
        // check that we can find a recipe with this name
        const recipe = this.recipes.find(rcp => rcp.Name === name);
        // if we can't, throw
        if (!recipe) throw new Error ("Don't know how to make " + name);

        // filter all ingredients we don't have enough of
        const missing = Object.keys(recipe.ingredients).filter(ing => 
            recipe.ingredients[ing] > this.state.Resources[ing]
        );
        // if that turns up anything, throw
        if (missing.length > 0) throw new Error ("Not enough " + missing.join(", "));

        // subtract the necessary amounts from the resources
        Object.keys(recipe.ingredients).forEach(ing =>
            this.state.Resources[ing] -= recipe.ingredients[ing]
        );

        // add finished item to the inventory
        if (!this.state.Inventory[name]) this.state.Inventory[name] = 0;
        this.state.Inventory[name]++;
    };
}

用法:

const myBakery = new Bakery({
    Money: 100,
    Resources: {
        Milk: 10,
        Eggs: 10,
        Flour: 10,
        Water: 10,
        Sugar: 10
    },
    Employees: {
        Bakers: 1,
        Cooks: 0,
        Servers: 0,
        Farmers: 0
    },
    Inventory: {
        Cake: 0,
        Cookies: 0
    },
}, [
    {Name: 'Cake', ingredients: {Milk: 1, Eggs: 2, Flour: 1}},
    {Name: 'Cookies', ingredients: {Eggs: 1, Flour: 1}},
]);

测试:

myBakery.bake('Baguette')  // -> Uncaught Error: Don't know how to make Baguette
myBakery.bake('Cake')
myBakery.bake('Cake')
myBakery.bake('Cake')
myBakery.bake('Cake')
myBakery.bake('Cake')
myBakery.bake('Cake')      // -> Uncaught Error: Not enough Eggs

改进意见:
改变 bake 从…起 function (name)function (name, amount) . 你不需要任何额外的线或循环。
测试当你打电话时会发生什么 bake 以否定的语气 amount .
测试当您关闭 amount 参数。
测试当你尝试烘焙一个蛋糕时会发生什么 cake 而不是 Cake .
使函数在所有这些情况下都能正常运行。

相关问题