模拟一堆卡片的最佳容器
Posted
技术标签:
【中文标题】模拟一堆卡片的最佳容器【英文标题】:Optimal container to simulate a pile of card 【发布时间】:2015-08-10 21:59:35 【问题描述】:我正在实现一个游戏,我正在寻找一个合适的容器来模拟一堆卡片。
强制条件:
-
容器可以随机打乱(需要
random iterators
,不包括std::list
)
容器可以分类
可以弹出第一个元素(从顶部抽一张牌)
可以在末尾插入元素(将卡片丢弃到底部)
到目前为止,我使用的是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
?
【问题讨论】:
std::vector
很好,但您可能还想看看std::deque
。
由于卡片是小东西,我只使用固定大小的数组。 C++ 程序员还记得如何使用“原始”数组,不是吗?
@LeeDanielCrocker,一些DistrictDeck
实例可以有更多或更少的卡片,我更喜欢坚持使用动态容器。我知道我可以模板类来构建一个定制的数组,但我喜欢保持较低的维护工作量。
使用vector
作为循环缓冲区,即保留起始和结束索引。它比deque
更好,因为在您的情况下,最大卡片数是有界的,
【参考方案1】:
Vector 可以很好地满足您的目的。使用Fisher Yates Shuffle 可以最佳地执行洗牌 (O(n))。
我还应该注意,基于 std::random_shuffle 的复杂性,这看起来已经是您正在使用的。
【讨论】:
【参考方案2】:首先,保留向量可能是一个不错的选择。
如果您必须经常移除卡片堆开头的元素,并且希望避免向量所需的大量移动,那么您可以选择 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
值得一提的是:双端队列具有随机迭代器,在恒定时间内在队列的开头或结尾执行插入/访问,虽然插入可能会使迭代器无效,但对元素的指针和引用仍然有效。
【讨论】:
【参考方案3】:保持矢量怎么样?这似乎是一个合理的选择——你希望在那里保留多少张卡片?连续存储通常更可取,因为这样可以避免大多数内存访问性能问题。
如果您知道要使用的最大卡片数,也可以使用 std::array 或纯数组。
与往常一样,衡量您的表现,看看您是否确实存在性能问题。
【讨论】:
我对 std::vector 的主要担心是关于绘图卡pileOfCards_.erase(std::begin(pileOfCards_));
从而转移内存,但我想对于 enum class
,这没什么大不了的。
对于少量卡片,复制这些枚举会很快。我猜你也不会每毫秒多次执行这个操作......
没错,我只是想知道一种更好的方法。以上是关于模拟一堆卡片的最佳容器的主要内容,如果未能解决你的问题,请参考以下文章