Можно ли использовать перехваченное исключение для перемещения по кругу вокруг массива? - PullRequest
1 голос
/ 08 марта 2012

Я пишу карточную игру, в которой игра проходит по кругу игроков (как и большинство карточных игр).Игра может идти в любом направлении влево или вправо и назначается логическому значению.Верно для игры справа, ложно для игры слева.У меня есть все объекты игрока в массиве, поэтому, когда мне нужно найти следующего игрока, который будет играть, я получу текущего игрока и назначу следующего игрока следующим игроком в списке.Если текущий игрок является последним игроком в списке, я получу исключение, скажем, за пределами ... если я не поймаю исключение и не назначу следующего игрока первым игроком в списке.Это нормальный способ сделать это?У меня нет других идей о том, как обойти список по кругу.Спасибо.

   public AbstractPlayergetNextPlayerToPlay(AbstractPlayer currentPlayer,             
   ArrayList<AbstractPlayer> players, boolean directionOfPlay){

    AbstractPlayer nextPlayerToPlay = null;

    //if the direction of play is forwards (true)
    if(directionOfPlay){
        for(int i=0;i<players.size();i++){
            try{
            if(players.get(i).equals(currentPlayer)){
                nextPlayerToPlay = players.get(i+1);
            }
            }catch(ArrayIndexOutOfBoundsException e){
                nextPlayerToPlay = players.get(0);//first player in the list
            }
        }
    }
    else{
        //if the direction of play is backwards (false)
        for(int i=players.size();i>0;i--){
            try{
            if(players.get(i).equals(currentPlayer)){
                nextPlayerToPlay = players.get(i-1);
            }
            }catch(ArrayIndexOutOfBoundsException e){
                nextPlayerToPlay = players.get(players.size());//last player in list  T
            }
        }
    }

    return nextPlayerToPlay;

}

Ответы [ 8 ]

2 голосов
/ 08 марта 2012

Попробуйте это, должны обрабатывать как назад, так и вперед

int currentPlayerIndex = players.indexOf(currentPlayer);
int nextPlayerIndex = currentPlayerIndex + (direction0fPlay ? 1 : -1);

// Ensure index is in array
nextPlayerIndex = (nextPlayerIndex + players.size()) % players.size();

return players.get(nextPlayerIndex);
1 голос
/ 08 марта 2012

Я бы порекомендовал посмотреть, будет ли связанный список соответствовать вашим потребностям.Специально прочитайте круглые связанные списки и двойные связанные списки.http://en.wikipedia.org/wiki/Linked_list

По сути, связанный список отслеживает набор элементов в заданном порядке.Вы начинаете с головного узла, головной узел указывает на следующий, который указывает на следующий, который указывает на следующий и т. Д.

В круговом связанном списке последний узел указывает на первый узел, завершающийкруг.В двусвязном списке узлы указывают на предыдущий узел, а также на следующий узел.Это решает проблему как обратного хода, так и обращения с последним игроком в списке.

Как правило, связанный список разбивается за длительное время поиска определенного узла, но вы, вероятно, могли бы сделать вещи болееэффективнее, обновляя ссылку на головной узел, чтобы он всегда был текущим игроком вместо статической начальной точки или чего-то подобного, что соответствует логике вашей игры.

1 голос
/ 08 марта 2012

Почему бы вам не попробовать

int playerIndex = 0;
while(true) {
    playerIndex++;
    if (playerIndex == players.size()) {
        playerIndex = 0;
    }

    [do your stuff with the player here]

}

Таким образом вы увеличиваете индекс игрока, пока не достигнете конца массива. Затем вы сбрасываете индекс на 0.

1 голос
/ 08 марта 2012

две вещи,
One:

for(int i=players.size();i>0;i--){

определенно сгенерирует исключение во время первой итерации, когда вы выполните players.get(i), когда выполняете итерацию в обратном порядке: вы должны начать с players.size()-1. Вы также можете захотеть повторить i>=0, [но тогда вы снова склонны к get(-1)]

Два: исключения являются медленными [относительно], и, хотя это возможно - обычно рекомендуется использовать логические операции, чтобы избежать такого поведения.
Вместо этого вы можете использовать i % size [кеш int size = players.size() перед итерацией], обратите внимание, что он не будет работать для get(-1), вам придется проделать некоторую [очень небольшую] дополнительную работу там. например, get((i+1+size) % size) и get((i-1+size) % size) всегда будут работать, если -size < i < size

0 голосов
/ 08 марта 2012

Вы можете представить круг игроков на двунаправленном наборе узлов, соединенных в круг, и просто спросить у узла (который представляет игрока) игрока следующего в зависимости от направления. Вы бы избежали обработки исключений и исчисления все вместе.

0 голосов
/ 08 марта 2012

Для верхнего предела оператор модуля % является вашим другом.

nextPlayerToPlay = players.get((i+1)%players.size()); 

(Возможно, вы захотите кэшировать player.size () в переменной)

нижний предел, так сложно проверить значение?

nextPlayerToPlay = players.get(i > 0 ? players.get(i-1): players.get(players.size()-1)); 
0 голосов
/ 08 марта 2012

Используйте оператор модуля, например. (i + 1 + Players.size ())% Players.size ()

Так что, если у вас было 6 игроков:

(6 + 1 + 7) % 7 = 0

Который вернется к первому игроку

0 голосов
/ 08 марта 2012

Изменить это

nextPlayerToPlay = players.get(i+1);

к этому

nextPlayerToPlay = players.get((i+1) % players.size());

Это оборачивает индекс обратно в 0, когда достигнут последний игрок, и намного эффективнее и элегантнее, чем бросать и ловить исключение.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...