最佳容器来模拟一堆卡片

时间:2015-08-10 21:59:35

标签: c++ algorithm c++11 optimization stl

我正在实施游戏,我正在寻找一个合适的容器来模拟一堆卡片。

强制性条件:

  1. 容器可以随机洗牌(需要random iteratorsstd::list除外)
  2. 可以对容器进行分类
  3. 可以弹出第一个元素(从顶部画一张卡片)
  4. 可以在末尾插入元素(丢弃卡片到底部)
  5. 到目前为止,我使用的是std::vector<District>,其中District是代表卡片值的enum class

    Live demo

    #include <vector>
    #include <algorithm>
    
    namespace Citadel
    {
        enum class District
        {
            UNINITIALIZED,
            FORTRESS,
            MANOR,
            // etc
        };
    
        class DistrictDeck
        {
        public:
            void Setup(const std::vector<District>& availableDistricts)
            {
                // Simplified filling...
                for (const auto district : availableDistricts)
                {
                    pileOfCards_.push_back(district);
                }
    
                // Once all cards have been pushed, shuffle them
                std::random_shuffle(std::begin(pileOfCards_), std::end(pileOfCards_));
            }
    
            // Pick a district card from top of the stack
            District Draw()
            {
                District district = District::UNINITIALIZED;
    
                if (pileOfCards_.size() > 0)
                {
                    district = pileOfCards_.front();
                    pileOfCards_.erase(std::begin(pileOfCards_));
                }
    
                return district;
            }
    
            // Put a district card below the bottom of the stack
            void Discard(const District district)
            {
                pileOfCards_.push_back(district);
            }
    
        private:
            std::vector<District> pileOfCards_;
        };
    }
    
    int main()
    {
    }
    

    在我的确切情况下,哪个容器可以替换std::vector

3 个答案:

答案 0 :(得分:2)

Vector适用于您的目的。可以使用Fisher Yates Shuffle最佳地执行混洗(O(n))。

我还应该注意到,基于std :: random_shuffle的复杂性,这已经成为你正在使用的东西。

答案 1 :(得分:1)

首先,保持载体可能是一个很好的选择。

如果你必须在一堆牌的开头删除非常频繁的元素并且想要避免向量所需的大量移动,那么你可以选择 deque

deque<int> q; 
default_random_engine rndgen;
q.push_front(11);
q.push_back(12);                     // requirement 4
q.push_front(15);
q.push_front(20); 
cout << q.front() <<endl;            // requirement 3
q.pop_front();                       //    "   "
cout << q.at(2)<<endl;               // + random access
sort(q.begin(), q.end());            // requirement 2
shuffle(q.begin(), q.end(), rndgen); // requirement 1

live demo

值得一提的是:deque具有随机迭代器,在常量时间内在队列的开始或结束时执行插入/访问,而插入可能使迭代器无效,指针和元素引用仍然有效。

答案 2 :(得分:0)

保持矢量怎么样?这似乎是一个合理的选择 - 你期望在那里留多少张牌?连续存储通常是首选,因为这可以避免大多数内存访问性能问题。

如果您知道要使用的最大卡数,也可以使用std :: array或仅使用普通数组。

与往常一样,衡量您的效果,看看您确实遇到了性能问题。