user7161409
user7161409

Reputation:

How do you return a boolean in a for loop

The first function call will return the string collided when the two objects collide so I know my logic is true. However a check of boolean returns nothing so i am stumped.

template <typename T, typename U>
void checkCollision(std::vector<T>  &vTower, std::vector<U>  &vMonster)
{
    for (int i = 0; i < vMonster.size(); i++)
    {
        for (int k = 0; k < vTower.size(); k++)
        {
            if (vMonster[i].getPositionX() + vMonster[i].getRadius() + 
                vTower[k].getRadius() > vTower[k].getTowerRangePositionX()
                && vMonster[i].getPositionX() < vTower[k].getTowerRangePositionX() + vMonster[i].getRadius() + vTower[k].getRadius()
                && vMonster[i].getPositionY() + vMonster[i].getRadius() + vTower[k].getRadius() > vTower[k].getTowerRangePositionY()
                && vMonster[i].getPositionY() < vTower[k].getTowerRangePositionY() + vMonster[i].getRadius() + vTower[k].getRadius())
            {
                std::cout << "Collided"
            }

        }
    }
};

This returns nothing when called from main

bool checkCollision(std::vector<T>  &vTower, std::vector<U>  &vMonster)
{
    for (int i = 0; i < vMonster.size(); i++)
    {
        for (int k = 0; k < vTower.size(); k++)
        {
            if (vMonster[i].getPositionX() + vMonster[i].getRadius() + vTower[k].getRadius() > vTower[k].getTowerRangePositionX()
                && vMonster[i].getPositionX() < vTower[k].getTowerRangePositionX() + vMonster[i].getRadius() + vTower[k].getRadius()
                && vMonster[i].getPositionY() + vMonster[i].getRadius() + vTower[k].getRadius() > vTower[k].getTowerRangePositionY()
                && vMonster[i].getPositionY() < vTower[k].getTowerRangePositionY() + vMonster[i].getRadius() + vTower[k].getRadius())
            {
                return true;
            }
            else
                return false;
        }
    }
}

This is in a endless window loop.

if(function.checkCollision(myicetower, mymonsters))
        std::cout << "TESTTESTTEST" << std::endl;

Upvotes: 0

Views: 322

Answers (2)

Corristo
Corristo

Reputation: 5510

As John pointed out, it suffices to move the return statement to the end. But you also might consider having a look at the standard algorithms.

Using std::any_of, your function could be rewritten to

bool checkCollision(std::vector<T> const& towers, std::vector<U> const& monsters) {
    auto const has_collision = [](T const& tower, U const& monster) {
        return monster.getPositionX() + monster.getRadius() + tower.getRadius() > tower.getTowerRangePositionX()
            && monster.getPositionX() < tower.getTowerRangePositionX() + monster.getRadius() + tower.getRadius()
            && monster.getPositionY() + monster.getRadius() + tower.getRadius() > tower.getTowerRangePositionY()
            && monster.getPositionY() < tower.getTowerRangePositionY() + monster.getRadius() + tower.getRadius();
    };

    return std::any_of(monsters.cbegin(), monsters.cend(),
        [&towers](auto const& monster) {
            return std::any_of(towers.cbegin(), towers.cend(),
                [&monster](auto const& tower) {
                    return has_collision(tower, monster);
                });
         });
}

which, while still not perfect, is much more readable (read it as "is there any monster, for which there is any tower with which it collides") and less error-prone than a handwritten loop.

If it is a common pattern in your code base to check if a pair of elements where the first is from one container and the second is from another container satisfies some condition you could also consider writing a custom any_of that encapsulates that so that you can write something like

bool checkCollision(std::vector<T> const& towers, std::vector<U> const& monsters) {
    auto const has_collision = [](T const& tower, U const& monster) {
        return monster.getPositionX() + monster.getRadius() + tower.getRadius() > tower.getTowerRangePositionX()
            && monster.getPositionX() < tower.getTowerRangePositionX() + monster.getRadius() + tower.getRadius()
            && monster.getPositionY() + monster.getRadius() + tower.getRadius() > tower.getTowerRangePositionY()
            && monster.getPositionY() < tower.getTowerRangePositionY() + monster.getRadius() + tower.getRadius();
    };

    return any_of(towers.cbegin(), towers.cend(),
                  monsters.cbegin(), monsters.cend(),
                  has_collision);
}

instead.

Upvotes: 0

John3136
John3136

Reputation: 29266

Your return false happens as soon as you find one object that doesn't match. It needs to be waaayyyyy down the function - at the bottom. Once you have checked everything and none match, at that point you can say nothing matches.

Upvotes: 1

Related Questions