Иерархия
Какое бы решение вы ни выбрали, клонирование всех 64 * 64 = 4096 элементов - это слишком много. Поскольку ваши изменения незначительны, вы можете использовать иерархическое неизменное представление , например, 64 × 64 массива, и всегда клонировать только те части, которые изменяются:
Piece[][] getModifiedClone(Piece[][] original, int x, int y, Piece newPiece) {
Piece[][] result = original.clone(); // clones 64 pointers only
result[x] = result[x].clone(); // also clones 64 pointers only
result[x][y] = newPiece;
return result;
}
Это уменьшает накладные расходы с 64 * 64 до 64 + 64. Вам не нужно следовать вашей структуре строк / столбцов здесь. За счет некоторой манипуляции с индексным битом вы можете использовать другую структуру. Вам не нужно организовывать внутреннюю иерархию как 2D; Вы можете использовать 3 или 4 уровня и уменьшить накладные расходы до 16 + 16 + 16 или 8 + 8 + 8 + 8.
Microoptimizations
Существует только один тип объекта, но у него есть три важные переменные. Все три являются целыми числами, которые всегда <= 2000. Я мог бы упаковать все это в одно целое, но преобразования назад и вперед уничтожили бы время доступа. </p>
Вы можете быть правы, но что-то вроде
int pack(int a, int b, int c) {
return (a << 22) + (b << 11) + (c << 0);
}
int unpackA(int packed) {
return (packed >> 22) & 0x7FF;
}
int unpackB(int packed) {
return (packed >> 11) & 0x7FF;
}
int unpackC(int packed) {
return (packed >> 0) & 0x7FF;
}
звучит намного быстрее, чем косвенное из-за использования объектов. Это может быть даже быстрее в микробенчмарке, использующем небольшой объем памяти и помещающемся в кэш L1. С большим количеством памяти и отсутствием кеша, упаковка IMHO - явный победитель.
Использование отмены
Возможно, это все еще слишком медленно, и тогда вы можете переосмыслить то, что делаете. Возможно, иметь только одну доску и отменить изменения, сделанные с ними, может быть быстрее, чем любое клонирование. Может быть, вам нужно более одной доски, может быть, по одной на поток ...
Основная информация
Полагаю, я бы выбрал комбинацию 4D-иерархии и упаковки, т. Е.
int getPackedPieceAt(int[][][][] board, int x, int y) {
return board[x >> 3][x & 7][y >> 3][y & 7];
}
Работа с массивами 4D довольно уродлива, но все, что вам нужно, это вышеописанный метод, а этот
int[][][][] getModifiedClone(int[][][][] original, int x, int y, int newPiece) {
... just like above
}
Предполагая, что ваше игровое состояние состоит не только из игрового поля, вы должны инкапсулировать массив в объект State
, который затем может скрыть все безобразия.