简体   繁体   中英

How to check if a string contains a certain element from an array, but not the other elements

I am making some chemistry game as a Telegram bot in JavaScript where you have an inventory and you need to mix the right chemicals. I have the inventory contained in an array, and in order to prevent brute-forcing your way to a level by simply pasting your inventory, I need to check if the user input contains the needed chemicals exclusively, and not any of the others in the array.

For example:

users[id].inventory = ["Beaker", "Water", "Baking soda", "Heating plate", "Hydrochloric acid"];

if (users[id].level === 1 && 
    msg.text.toLowerCase().indexOf('baking soda') !== -1 &&
    msg.text.toLowerCase().indexOf('hydrochloric acid') !== -1 && 
    msg.text.toLowerCase().indexOf('beaker') === -1 && 
    msg.text.toLowerCase().indexOf('water') === -1 && 
    msg.text.toLowerCase().indexOf('heating plate') === -1) {

    msg.answer("You mix some baking soda with hydrochloric acid.\nSome fun fizzing happens and you produce useless CO2 gas.");
}

At higer levels you will get a much larger inventory and this will lead to very large if-statements this way. This looks bad and there must be a better way. Is there such thing like an exclusive indexOf() or any other solution? I have checked out arr.filter() for example but I can't find out a good way to implement this.

Checking for every ingredient manually is not a good idea, as you point out it will become very tedious if the requirements for a recipe are long and the inventory is also long.

I suggest creating a function rightIngredients that takes two arrays: the requirements and the items used.

Considering that only the items in the recipe should be used, the first thing I'd do inside the function is to check the length of both arrays. If they are different then it should return false and nothing else needs to be checked.

If the length of the arrays is the same, then we check each of the items used to see if they are in the requirements. If one of them is not, then we return false as well.

requirements = ["baking soda", "hydrochloric acid"];

function rightIngredients(req, uses) {
    if (uses.length != req.length) {
    console.log(uses.join(', ')+' are not even the right amount of ingredients');
    missing = true;
  } else {
    var i = 0;
    var missing = false;
    while (i<uses.length && !missing) {
        if (req.indexOf(uses[i].toLowerCase())===-1) missing = true;
      ++i;
    }
    if (missing) console.log(uses.join(', ')+' are not the right ingredients');
    else console.log(uses.join(', ')+' are the right ingredients');
  }
  return !missing;
}
rightIngredients(requirements, ["Beaker", "Baking Soda", "Hydrochloric Acid"]);
// Beaker, Baking Soda, Hydrochloric Acid are not even the right amount of ingredients
rightIngredients(requirements, ["Beaker", "Baking Soda"]);
// Beaker, Baking Soda are not the right ingredients
rightIngredients(requirements, ["Baking Soda", "Hydrochloric Acid"]);
// Baking Soda, Hydrochloric Acid are the right ingredients

You can create an array of all disallowed chemicals and then use Array.every to check if all elements satisfy this condition. Also you will have different combination based on level, so I would suggest to create a map of level and disallowed chemicals and make the function generic.

Following is a sample:

// Map object of Level and Chemicals
var map = [{
  level: 1,
  disallowed_chemicals: ['baking soda', 'hydrochloric acid', 'beaker', 'water', 'heating plate']
}];

// getter function to get map object for current level.
// If this returns undefined you can assume, incorrect level is entered
function getLevelMap(u_level) {
  return map.find(function(o) {
    return o.level === u_level;
  });
}

var m_level = getLevelMap(users[id].level);
if (m_level &&
  m_level.every(function(ch) {
    return msg.toLowerCase().indexOf(ch) < 0;
  })) {

  msg.answer("You mix some baking soda with hydrochloric acid.\nSome fun fizzing happens and you produce useless CO2 gas.");
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM