在瓷砖匹配游戏逻辑中使用 STL 算法
Posted
技术标签:
【中文标题】在瓷砖匹配游戏逻辑中使用 STL 算法【英文标题】:Use of STL algorithms in a tile matching game logic 【发布时间】:2018-04-15 23:44:13 【问题描述】:我制作了一个拼图游戏。它有一个 Board 对象,其中包含卡片对象的向量并将事件委托给它们。 Board 事件处理中包含以下代码:
// Counting logic-driving card states
int cardFaceUpCounter = 0;
std::vector<Card*> faceUpCards(2);
// Checking for logic-driving card states
for (auto& card : this->boardMatrix)
if (this->isCardInAnim(&card))
return;
if (this->isCardFaceUp(&card))
++cardFaceUpCounter;
faceUpCards[cardFaceUpCounter - 1] = &card;
我刚刚在 Pluralsight 上完成了 Kate Gregory 的 Beautiful C++ 学习。 她认为我们应该避免编写循环,并且应该尽可能地使用 STL 算法头。 我发现她的论点和方法非常有说服力,因此我尝试重构我最新的宠物项目以反映她的教义。
上面的示例是我无法看到如何使用 STL 算法来更好地传达意图并保持性能 - 单个循环而不是两个或三个循环,尽管隐藏在算法调用中。
第二个问题是,如果使用 STL 算法无法实现单循环效率,出于可读性的考虑,您是否仍然更喜欢这种方法。
【问题讨论】:
你为什么期待两张而且只有两张正面朝上的牌?你可以把它写成一个容器到另一个容器的标准转换。 我的游戏被设置成任何时候只能出两张牌。事件只能触发一个卡牌回合,因此如果检测到两张卡牌,下一个事件(点击),如果相同则丢弃它们,如果不同则将它们返回。 通常最好使用push_back
,以防您的假设错误。此外,它使您的算法更通用。
如果我的假设是错误的,我的游戏逻辑就会中断,如果我的代码中断比逻辑中断,我更容易找到错误。但我会进一步研究你的评论。真诚的感谢。
另外,你认为我的推理有效吗?
【参考方案1】:
这是我的想法的一个例子。
int cardFaceUpCounter = 0;
std::vector<Card*> faceUpCards(2);
if (std::any_of(boardMatrix.begin(), boardMatrix.end(), [&](auto& card)
if (isCardFaceUp(&card))
faceUpCards[cardFaceUpCounter++] = &card;
return isCardInAnim(&card);
)) return;
【讨论】:
哇,太好了 :) 我会在早上接受它,当我要深入研究这个问题时。谢谢 :) 为了完整起见,您可以添加 if(any_of()) return;因为动画打破了我的循环。 我认为这回答了我的第一个问题。但是你认为这段代码比我写的更具可读性吗?我知道这是我要求的意见,但有时你不能没有他们:) 我尝试写一些更有表现力的东西,但我最终写了一个 find_all func,一个 std::find_if 在一个保存到向量的循环中。这似乎不值得麻烦。 @AntonioDropulić 既然你想结束外部函数,我可能会自己去一个循环。 我会避免在std::any_of
中使用副作用。【参考方案2】:
使用range-v3,会是这样的:
std::vector<Card*> faceUpCards = this->boardMatrix
| ranges::view::take_while([this](const auto& card) return !isCardInAnim(&card);)
| ranges::view::filter([this](const auto& card) return isCardFaceUp(&card); )
| ranges::view::transform([](auto& e) return &e; );
仅使用 STL,我会执行以下操作:
auto it = std::find_if(boardMatrix.begin(), boardMatrix.end(),
[this](const auto& card) return isCardInAnim(&card););
std::vector<Card*> faceUpCards(std::distance(boardMatrix.begin(), it), nullptr);
std::transform(boardMatrix.begin(), it,
faceUpCards.begin(),
[](auto& card) return &card;);
faceUpCards.erase(std::remove_if(faceUpCards.begin(), faceUpCards.end(),
[this](const auto& card) return !isCardFaceUp(&card); ),
faceUpCards.end());
【讨论】:
告诉我如果我读你的代码很好。您希望所有正面朝上的卡片都在 begin 和 card in anim 之间,并且您希望 begin 和 card in anim 之间的所有卡片都向上。还要感谢范围示例,但我目前正在尝试掌握 STL - 新手问题:) 我支持范围 - v3 lib,不确定 stl 示例是否正确。 确实,我错过了关于isCardFaceUp
的两种情况的过滤。固定。以上是关于在瓷砖匹配游戏逻辑中使用 STL 算法的主要内容,如果未能解决你的问题,请参考以下文章