这样做的目的是使if语句的顶部不是底部的首选。我尝试为每个案例分配枚举值。然后选择一个从0到包含那些枚举元素的std::list myList
大小的随机整数r。使用it = std::next (myList, r)
找到枚举值。然后,如果对应于该枚举值的if语句为false
,则为myList.erase (it)
,并使用新的myList
重复该过程。它工作,一切似乎很随机。但令人失望的是,比我使用原始if-else
语句慢得多。对更快的方法有什么建议吗?
这是我的代码片段。有一群女孩。每个人都会选择一个女孩,然后选择一个面向的方向与他选择的女孩一起跳舞。但是,如果有人站在他想要站立的位置以获得他想要的面向方向,并非所有面向方向都是可能的。如果没有随机化if-else
语句,大多数人最终都会面对同样的方向,这是我不喜欢的。
std::list<FacingDirection> guyFacingDirections = {Positive_x, Negative_x, Positive_y, Negative_y, Positive_xPositive_y, Positive_xNegative_y, Negative_xPositive_y, Negative_xNegative_y};
while (true) {
const int r = rand() % guyFacingDirections.size();
std::list<FacingDirection>::iterator it = std::next(guyFacingDirections.begin(), r);
const FacingDirection facingDirectionChoice = *it;
if (facingDirectionChoice == Positive_x) // I decided that using switch (facingDirectionChoice) {case Positive_x: if (... was too clumsy in code and probably no more efficient.
{
if (mainArea.locationAvailable (xChoice - 1, yChoice, zChoice))
{guy->movesToNewLocation (xChoice - 1, yChoice, zChoice); break;}
else
guyFacingDirections.erase (it); // more efficient than 'guyFacingDirections.remove (Positive_x);'
}
else if (facingDirectionChoice == Negative_x)
{
if (mainArea.locationAvailable (xChoice + 1, yChoice, zChoice))
{guy->movesToNewLocation (xChoice + 1, yChoice, zChoice); break;}
else
guyFacingDirections.erase (it);
}
else if (facingDirectionChoice == Positive_y)
{
if (mainArea.locationAvailable (xChoice, yChoice - 1, zChoice))
{guy->movesToNewLocation (xChoice, yChoice - 1, zChoice); break;}
else
guyFacingDirections.erase (it);
}
else if (facingDirectionChoice == Negative_y)
{
if (mainArea.locationAvailable (xChoice, yChoice + 1, zChoice))
{guy->movesToNewLocation (xChoice, yChoice + 1, zChoice); break;}
else
guyFacingDirections.erase (it);
}
else if (facingDirectionChoice == Positive_xPositive_y)
{
if (mainArea.locationAvailable (xChoice - 1, yChoice - 1, zChoice))
{guy->movesToNewLocation (xChoice - 1, yChoice - 1, zChoice); break;}
else
guyFacingDirections.erase (it);
}
else if (facingDirectionChoice == Positive_xNegative_y)
{
if (mainArea.locationAvailable (xChoice - 1, yChoice + 1, zChoice))
{guy->movesToNewLocation (xChoice - 1, yChoice + 1, zChoice); break;}
else
guyFacingDirections.erase (it);
}
else if (facingDirectionChoice == Negative_xPositive_y)
{
if (mainArea.locationAvailable (xChoice + 1, yChoice - 1, zChoice))
{guy->movesToNewLocation (xChoice + 1, yChoice - 1, zChoice); break;}
else
guyFacingDirections.erase (it);
}
else if (facingDirectionChoice == Negative_xNegative_y)
{
if (mainArea.locationAvailable (xChoice + 1, yChoice + 1, zChoice))
{guy->movesToNewLocation (xChoice + 1, yChoice + 1, zChoice); break;}
else
guyFacingDirections.erase (it);
}
}
答案 0 :(得分:0)
好消息,你可以让这个运行更快,使代码更短,更清晰,更容易移动...更不用说给你想要的行为了 - 一切都很简单:)
定义面向方向的列表:
class HandleFacingDirection {
final int x;
final int y;
HandleFacingDirection(int x, int y) {
this.x = x;
this.y = y;
}
public boolean canFace(int xChoice, int yChoice, int zChoice) {
if (mainArea.locationAvailable (xChoice + x, yChoice + y, zChoice)) {
guy->movesToNewLocation (xChoice + 1, yChoice, zChoice);
return true;
}
return false;
}
}
然后定义一个数组:
HandleFacingDirection[] directionHandlers = new HandleFacingDirections[] {
new HandleFacingDirection(1, 0),
new HandleFacingDirection(-1, 0),
new HandleFacingDirection(0, 1),
new HandleFacingDirection(0, -1)
}
在某处定义随机数生成器:
Random random = new Random();
现在你处理它的代码变成了:
int offset = random.nextRandomInt(directionHandlers.length);
for (int i=0;i<directionHandlers.length;i++) {
int index = i+offset;
if (index > directionHandlers.length)
index -= directionHandlers.length;
if (directionHandlers[index].canFace(xChoice, yChoice, zChoice)) {
break;
}
}
一般的想法是你定义一个策略模式来确定某些东西是否有效。
然后,您可以设置一个列表,其中包含该策略模式的所有各种排列。
然后从随机位置开始遍历列表 。
上面的代码可能需要整理一下,因为我把它放在一起,它应该给你一些东西可以建立。
答案 1 :(得分:0)
是的,我确实尝试了以下内容:
struct Direction {
int delta_x;
int delta_y;
// FacingDirection dir; // if this information is also desired
};
static std::vector<Direction> directions = { {1, 0}, {-1, 0}, {0, 1}, {0, -1}, {1, 1}, {1, -1}, {-1, 1}, {-1, -1} }; // static so that it only needs be initialized once
std::random_shuffle (std::begin (directions), std::end (directions));
//FacingDirection chosenDirection; // use this if this information is needed (currently it is not)
for (const Direction& d: directions) // Range-based for-loop MIGHT give faster performance.
{
const int x = xChoice + d.delta_x;
const int y = yChoice + d.delta_y;
if (mainArea.locationAvailable (x, y, zChoice))
{
guy->movesToNewLocation (x, y, zChoice);
//chosenDirection = d.dir; // currently not needed for my program
break;
}
}
感谢JLBorges提出这个建议。事实证明,它的执行速度并不比我原来的方法快,但它解决了处理任意大量案例的问题。
似乎没有办法随机化if-else语句的顺序,同时使性能几乎与非随机的if-else语句集相匹配。它应该是C ++ 14委员会的工作。
答案 2 :(得分:0)
将JLBorges和TimB的想法结合起来的最后一次尝试:
struct Direction {
int delta_x;
int delta_y;
// FacingDirection dir; // if this information is also desired
bool canFace (Guy* guy, int x, int y, int z) const {
if (guy->LocationSituated()->locationAvailable (x + delta_x, y + delta_y, z))
{
guy->movesToNewLocation (x + delta_x, y + delta_y, z);
return true; // return std::make_pair (true, dir); if FacingDirection information is needed (currently it is not)
}
return false;
}
};
static std::vector<Direction> directions = { {1, 0}, {-1, 0}, {0, 1}, {0, -1}, {1, 1}, {1, -1}, {-1, 1}, {-1, -1} }; // static so initialization only once
std::random_shuffle (std::begin (directions), std::end (directions));
for (const Direction& d: directions) // Range-based for-loop MIGHT give faster performance
if (d.canFace (guy, xChoice, yChoice, zChoice))
break; // (xChoice, yChoice, zChoice) is the position of the girl he wants to dance with
但与第一种方法相比,性能仍然没有提高。但是代码现在更加优雅和灵活。
答案 3 :(得分:0)
您使用的是错误的解决方案。
这就是问题所在。
大多数人最终会面对同样的方向,我不喜欢。
解决方案是使用随机数来影响方向。不要使用随机数来影响代码生成。
使用随机数来影响代码生成存在以下问题:
一个想法可以解决您的问题: