1

Can someone help me finding the logical error in the code bellow? When it runs, the program displays all as "not guilty" despite one of the objects in the array satisfies the condition.

var suspectsArray = [
{ 
    "name": "BRIDGET ASHELY",
    "glasses": "very thick",
    "accessory": "metal briefcase",
    "eyes": "pale",
    "height": 155,
    "age": 63
},
{ 
    "name": "LIANNE NIEMELA",
    "glasses": "blue",
    "accessory": "plastic box",
    "eyes": "brown",
    "height": 150,
    "age": 47
},
{ 
    "name": "JAUNITA FORSLIN",
    "glasses": "dark brown",
    "accessory": "laptop bag",
    "eyes": "grey",
    "height": 182,
    "age": 58
},
{ 
    "name": "JULIANA DEAUVILLE",
    "glasses": "red",
    "accessory": "glass bottle",
    "eyes": "green",
    "height": 175,
    "age": 34
},
{ 
    "name": "LINETTE DORCEY",
    "glasses": "light tan",
    "accessory": "big black envelope",
    "eyes": "blue",
    "height": 178,
    "age": 43
}
];

var myFont;
var backgroundImg;

function preload() {
 myFont = loadFont('SpecialElite.ttf');
 backgroundImg = loadImage("Background.png");
}

function setup()
{
createCanvas(640,480);
textFont(myFont);
}


function matchSuspect(suspectObj){

    for (var k = 0; k < suspectsArray.length; k++)
    {
        if(
        suspectsArray[k].glasses == "blue" &&
        suspectsArray[k].accessory == "plastic box" &&
        suspectsArray[k].eyes == "brown" &&
        suspectsArray[k].height > 141 &&
        suspectsArray[k].age < 49
    ){
        return true;
    }

        return false;
    }
    }
function draw()
{

  image(backgroundImg, 0, 0);

  for(let i = 0 ; i < suspectsArray.length; i++){
    if(matchSuspect(suspectsArray[i]) == true){
      fill(255,0,0);
      text(suspectsArray[i].name + " is guilty!", 60, 60 + i * 20);
    }else{
      fill(0,155,0);
      text(suspectsArray[i].name + " is not guilty", 60, 60 + i * 20 );
    }
  }
}

If running correctly, it should display the second object in the array in red. I am not sure if the iterations are wrong or what. To experiment with that I tried using || instead of && and the logic was correct (or so the program gave the right answers).

It looks to me like a simple solution, but I spend a very long time on it and couldn't get to it :/

David
  • 208,112
  • 36
  • 198
  • 279
FabioD
  • 13
  • 4
  • 2
    Welcome to Stack Overflow! This is a good opportunity for you to start familiarizing yourself with [using a debugger](https://stackoverflow.com/q/25385173/328193). When you step through the code in a debugger, which operation first produces an unexpected result? What were the values used in that operation? What was the result? What result was expected? Why? To learn more about this community and how we can help you, please start with the [tour] and read [ask] and its linked resources. – David Feb 06 '23 at 16:16
  • 1
    You should use the `suspectObj` parameter somewhere in `matchSuspect()` – Moritz Ringler Feb 06 '23 at 16:29
  • 1
    Your `for` loop `if` inside of `matchSuspect` returns true or false after only testing the first suspect. The parameter is ignored. There's no need for 2 loops here, just test one suspect in `matchSuspect`. If you used correct indentation, this would be easier to detect. See [how to debug small programs](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/). – ggorlen Feb 06 '23 at 16:43
  • 1
    `matchSuspect()` doesn't need a loop. It should only be checking the one suspect that's passed as the argument, not all the suspects. The loop is in `draw()`. – Barmar Feb 06 '23 at 16:44

4 Answers4

2

The issue here is that your function ignores the object passed in as a parameter and instead loops through the entire array, but will return as soon as the first person is checked, hence why you are always getting false for every person passed in as a parameter.

To fix this, try removing your for loop inside the function and only process the object being passed in as the parameter instead.

function matchSuspect(suspectObj){

    if(
    suspectObj.glasses == "blue" &&
    suspectObj.accessory == "plastic box" &&
    suspectObj.eyes == "brown" &&
    suspectObj.height > 141 &&
    suspectObj.age < 49
    ){
      return true;
    }

    return false;
}
TheYuriG
  • 134
  • 1
  • 9
  • Thank you all for the help and assistance. Appreciate all the tips regarding style and passing arguments. Sorry I am a newbie to this but I am overwhelmed and grateful to all for being kind and respectful. Thanks a million! – FabioD Feb 06 '23 at 17:11
1
  • matchSuspect - pass suspects and suspect to it, for better code quality.
  • draw - pass suspects and matchSuspect to it
  • use === not ==
  • fix your styling, would be easier to see.
  • you loop twice, once in matchSuspect and once in draw, remove the loop from one of them.

You need an else after your true, you return false after the first element in your array.

Jeremy
  • 1,170
  • 9
  • 26
  • 1
    `draw()` is a p5 function so you can't pass args to it. It's called by the library. As for `matchSuspect`, usually pass a whole array or a single item, but not both. – ggorlen Feb 06 '23 at 16:49
  • Was assuming this was just vanilla, is there a lib in use? We use multiple args all the time: haystack, needle and the function do what it needs. Better to pass by prop / make it more pure than let the function reach out from inside. – Jeremy Feb 06 '23 at 16:55
  • Good point, if you're searching for an item in an array, that's one use case, but it'd be silly to call that function with a member of that array. You'd call it with something you got elsewhere and aren't sure if it's in the array. Also, what we have here isn't an array search so the example doesn't apply. p5 is the lib here. – ggorlen Feb 06 '23 at 16:56
  • Also a valid point! – Jeremy Feb 06 '23 at 16:57
1

matchSuspect() should only test the one subject that's passed in suspectObj.

function matchSuspect(suspectObj) {
  return suspectObj.glasses == "blue" &&
    suspectObj.accessory == "plastic box" &&
    suspectObj.eyes == "brown" &&
    suspectObj.height > 141 &&
    suspectObj.age < 49;
}
Barmar
  • 741,623
  • 53
  • 500
  • 612
1

In the matchSuspect function, when the first iteration runs for the first object of the array, the condition in the if is false and so it gets to the return false; expression and the entire function ends and you don't get to do the other iterations. Basically this means that the function always returns false.

Furthermore, you don't really use the matchSuspect function's parameter suspectObj. Did you mean to do something else?

Maybe you wanted to do something like this?

function matchSuspect(suspectObj) {
    if (suspectObj.glasses == "blue" &&
        suspectObj.accessory == "plastic box" &&
        suspectObj.eyes == "brown" &&
        suspectObj.height > 141 &&
        suspectObj.age < 49
    ) {
        return true;
    }
    
    return false;
}

function draw() {
    image(backgroundImg, 0, 0);

    for(let i = 0 ; i < suspectsArray.length; i++) {
        if (matchSuspect(suspectsArray[i]) == true) {
            fill(255,0,0);
            text(suspectsArray[i].name + " is guilty!", 60, 60 + i * 20);
        } else {
            fill(0,155,0);
            text(suspectsArray[i].name + " is not guilty", 60, 60 + i * 20 );
        }
    }
}
Shai
  • 3,659
  • 2
  • 13
  • 26