迭代for循环的最佳方法,然后再向后迭代它?

时间:2014-05-05 20:03:19

标签: c++ loops for-loop iterator

我发现在编写动画时,我有时会遇到一次for循环,然后再重复该值。这通常用于跳跃动画,或者消失然后再次出现动画。

这是我做过的一个例子 -

// Make the sprite slowly disappear
for (int i = 256; i > 0; --i)
{
    sprite.opacity(i);
    draw();
}

// Make the sprite slowly appear again
for (int i = 0; i < 256; ++i)
{
    sprite.opacity(i);
    draw();
}

每次我这样做,我都深深感到它太过分了。什么是更好的方式来解决这个问题?我不完全确定什么是最佳做法。我想我可以使用reverse_iterator,但我也不确定如何实现它。

6 个答案:

答案 0 :(得分:12)

考虑使用<cmath> abs()函数:

for( int i = -255; i <= 255; i++)
    use( abs( i ) );

答案 1 :(得分:2)

您可以使用abs()中定义的绝对值函数<cmath>。它会将您的代码中的代码减半。

for(int i=0; i<512; ++i)
{
    sprite.opacity( abs(256-i) );
    draw();
}

答案 2 :(得分:1)

这是迭代循环和“反向”循环的好方法 - 这是C ++程序员常用的循环。

对于你的精灵,似乎只需要256范围(你可以考虑设置const int RGB_RANGE等于256 - 或更合适的标识符);但是,如果您的对象的大小是动态的,您还可以考虑使用.size()函数(类似于ArrayListvector - 这里就像迭代器一样有用) :

for (i = 9; i < RGB_RANGE; i++)
{
    // CODE
}

以上代码是第一个const建议的示例。请记住,简单的代码从来都不是坏事 - 这意味着你正在做正确的事情。

答案 3 :(得分:1)

我相信你所描述的情况,你必须遍历精灵来设置每个精灵的不透明度。无论您使用for循环还是reverse_iterator,花费的时间都是相同的。 reverse_iterator的任何实现仍然必须遍历每个sprite。可能有一些方法可以让它更容易阅读,但最终算法将归结为相同。例如,您可以利用堆栈并递归调用精灵来增加不透明度,然后在退出的路上减少;但是,我认为这样做没有任何好处,算法时间仍然会变得相同。

在某些情况下,你只需要咬紧牙关,花点时间做一些看似(甚至是)暴力的事情。

答案 4 :(得分:1)

如果您不想使用abs,我会选择以下内容:

template<typename Func>
void animate (size_t step_count, Func && f)
{
    size_t step;

    for (step = step_count ; step > 0 ; --step)
        f(step - 1);

    for (step = 1 ; step < step_count ; ++step)
        f(step);
}

用例:

animate(256, [](size_t step)
{
    sprite.opacity(step);
    draw();
});

答案 5 :(得分:1)

如果你想再次上下调整一个范围,你可以走非常疯狂的路线,只需定义一个提供迭代器的“容器”(或范围,在boost语言中)(从技术上讲,它们更接近于 - 迭代器),它允许您准确表达您打算做什么:

for(auto i : down_and_up(3)) ::std::cout << i << "\n";

例如应该打印

3
2
1
0
1
2

可悲的是,标准库中对此类型的支持不多,虽然此处提供了boost::iterator_rangeboost::counting_iteratorboost::join,与std::reverse_iterator一致,可以提供down_and_up。只要你没有完全滥用它,就自己写一个(虽然很冗长):

struct down_and_up
{
    size_t from;
    down_and_up(size_t const from) : from(from) { }
    struct iterator : public ::std::iterator<::std::forward_iterator_tag, size_t> {
        size_t cur;
        bool down;

        iterator(size_t cur, bool down) : cur(cur), down(down) { }

        size_t operator*() const { return cur; }
        iterator& operator++()
        {
            if(down)
            {
                --cur;
                if(0 == cur) down = false;
            }
            else ++cur;
            return *this;
        }
        friend bool operator==(iterator const& lhs, iterator const& rhs) { return lhs.down == rhs.down && lhs.cur == rhs.cur; }
        friend bool operator!=(iterator const& lhs, iterator const& rhs) { return lhs.down != rhs.down || lhs.cur != rhs.cur; }
    };


    iterator begin() const { return iterator{ from, true }; }
    iterator end() const { return iterator{ from, false }; }
};

注意:如果您愿意,可以使用更多容器功能轻松扩展它,例如value_type成员typedef,但此定义足以满足上述示例。

P.S。:为您的娱乐提升方式:

boost::iterator_range<boost::counting_iterator<size_t>> up(boost::counting_iterator<size_t>(0), boost::counting_iterator<size_t>(3));
boost::iterator_range<std::reverse_iterator<boost::counting_iterator<size_t>>> down(
    std::reverse_iterator<boost::counting_iterator<size_t>>(boost::counting_iterator<size_t>(4)),
    std::reverse_iterator<boost::counting_iterator<size_t>>(boost::counting_iterator<size_t>(1)));

for(auto i : boost::join(down, up)) ::std::cout << i << "\n";