2013-12-11 7 views
1

Целью этого является то, что верхняя часть операторов if не является предпочтительной в нижней части. Я попытался присвоить значения enum каждому случаю. Затем выберите случайное целое число от 0 до размера std::list myList, содержащего эти элементы перечисления. Значение перечисления найдено с использованием it = std::next (myList, r). Затем, если оператор if, соответствующий этому значению перечисления, равен false, затем myList.erase (it) и повторите процесс с помощью нового уменьшения myList. Он работает, и все кажется хорошо рандомизированным. Но это неутешительно намного медленнее, чем когда я использовал оригинальные заявления if-else. Любые предложения для более быстрого метода?
Вот фрагмент моего кода. Есть толпа девушек. Каждый парень выберет девушку, а затем выберет направление для танца с выбранной девушкой. Но не все направленные стороны возможны, если кто-то стоит на том месте, где он хочет встать, чтобы получить желаемое направление. Без рандомизации заявлений 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

Каков именно контекст здесь? Некоторые блоки if изменяют условные выражения других операторов if? Почему необходимо рандомизировать это поведение? –

+0

Вот фрагмент моего кода (извините, если формат выглядит не очень хорошо - я здесь новый). – prestokeys

+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; 
    } 
} 

Основная идея заключается в том, что ваш определить шаблон стратегии, чтобы определить, есть ли действительно что-то.

Затем вы настраиваете список, содержащий все различные перестановки этого шаблона стратегии.

Затем вы переходите через список , начиная с случайной позиции.

Этот код, возможно, нуждается в некотором уборе, поскольку я просто бросил его вместе, он должен дать вам кое-что, чтобы опираться на него.

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.

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 

Но до сих пор никаких улучшений в производительности по сравнению с моим первым способом. Но теперь код намного более элегантный и гибкий.

0

Вы ошиблись.

В этом проблема.

Большинство ребят в конечном итоге окажутся в том же направлении, что мне не нравится.

Решение заключается в использовании случайных чисел для воздействия на направление. Не используйте случайные числа, чтобы повлиять на формирование кода.

Использование случайных чисел влиять генерации кода имеет следующие проблемы:

  • Это будет медленнее (как вы уже определили)
  • Компилятор может эффективно изменить порядок утверждения в любом случае (по сравнению с вашим исходным кодом). Таким образом, вы просто сражаетесь с компилятором, что не очень хорошо.
  • Добавляет сложности, что делает программу труднее понять, поддерживать, отладку и т.д.


Одна идеи решить вашу проблему:

  1. Генерирует случайное направление обращенного.
  2. Если это направление заблокировано, выберите произвольное направление вращения.
    • Затем поверните символ (в выбранном направлении), пока он не обнаружит разблокированную ориентацию.
+0

Но шаг 1 не разрешен в моей программе. Место уже установлено (девушка, с которой он хочет потанцевать). Он должен просто выбрать место рядом с ней, которое доступно (там будет место, потому что девушка уже выбрала место, где есть место рядом с ней, которое пусто). Я уже опубликовал два решения, предложенные другими, и мои тесты не показали улучшения в производительности, но их коды намного лучше. – prestokeys

+0

@ user3089350 Удален шаг 1 для соответствия заданному набору. –

Смежные вопросы