我有一段代码可以为玩家生成迷你任务。这很简单,要获得两个不同的点(起点和终点),我有一个如下所示的算法:
std::vector missions;
missions.push_back("Location_One");
missions.push_back("Location_Two");
missions.push_back("Location_Three");
//make sure our data has at least 2 elements (so we can actually pick two)
if(missions.size() > 1)
{
//Rand(inclusive min, exlusive max)
int mission_start_location = Rand(0,missions.size());
int mission_end_location = Rand(0,missions.size());
if(mission_start_location == mission_end_location)
{
//avoid possile infinite loop of calling "Rand" by Add/Decrement-if-equal algorithm
//basicly if mission_start_location == 0
if(!mission_start_location)
++mission_end_location;//or = 1, we have at least two elements so index 1 is valid
khác
--mission_end_location;//so we won't got out of range
}
//do mission
}
khác
{
//error
}
这行得通,但是我想知道是否有更好的方法来实现我想要的,“C++ 方式”。
Câu hỏi của tôi là:
- 这是从容器中获取两个不同值的最佳方式吗?
- 非整数索引容器(例如
std::map
)呢?
-
注意:我非常了解 do { } while(rand1 == rand2)
方法。我想避免这种情况,因为它Có thể进入无限循环(我知道它会在生产代码中出现)。
是的,你可以用另一种方式。
if(missions.size() > 1)
{
size_t const m_size = missions.size();
// get random number in the full range
int const m_start = Rand(0, m_size);
// get another number in a range reduced by 1
int m_end = Rand(0, m_size-1);
// if we are equal or above start we shift by 1 up
if (m_end >= m_start) ++m_end;
}
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
如果您的第一个选择选择 4,则通过在范围 1 上设置第二个随机数来虚拟地删除它。
| 0 | 1 | 2 | 3 | 4(was 5) | 5(was 6) | 6(was 7) |
要将第二个随机数映射回原始索引,如果您高于第一个随机数,则只需添加 1,因为由于第一个索引的“删除”,这些索引移动了 1。
这样,在第一次
Rand()
调用中未选择的每个索引在第二次调用
Rand()
时以相同的概率被选中。 (如果您的
Rand()
实现提供了这种适当的随机数分布。)
Tôi là một lập trình viên xuất sắc, rất giỏi!