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

时间:2021-07-09 16:39:26

标签: javascript arrays object

我正在使用 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 中的数量,然后将适当的项目(蛋糕/饼干)添加到 {{1} }库存。

我尝试了几种不同的方法来解决这个问题,这几乎需要针对每种成分类型的单独函数,这对我来说似乎效率极低。

此外,一些将被烘烤的物品会省略一些成分(饼干不需要牛奶)。因此,如果该函数检查此/仅从理想的 mainObj 库存中删除必需的项目,实际上,这是必要的。

如果有人能指出我正确的方向,那就太好了。

3 个答案:

答案 0 :(得分:1)

上述 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);

答案 1 :(得分:0)

这应该有效:

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!")

答案 2 :(得分:0)

使用下面的 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; }

相关问题