#java #data-structures #integer
Вопрос:
я оптимизирую и повышу производительность кода, который дает учитель для игры в крестики-нолики. Поскольку я буду использовать только X = 1, O = -1 и EMPTY = 0, я не хочу хранить эти числа в 32-битном массиве int. Могу ли я создать свой класс так же, как класс int, но только с 1, 0, -1. Я хочу это сделать;
public static final int X = 1, O = -1, EMPTY = 0;
myDataType[][] board = new myDataType[3][3];
board[0][0] = X;
board[0][1] = O;
Комментарии:
1. О чем
byte
?2. Можете ли вы привести пример использования?
3. Просто чтобы мне было ясно, по сути, вы хотите, чтобы класс имел значение int, равное 1, 0, -1? Это означает, что класс будет иметь одно поле, которое является значением int, и ничего больше?
4. Похоже, вы хотите использовать перечисление
5. Ссылка на экземпляр класса-оболочки, вероятно, заняла бы еще больше памяти.
Ответ №1:
Чтобы ответить на ваш вопрос. Давайте предположим, что вы можете использовать логическое значение (примитивный тип данных с простым » b » для вашего массива). Теоретически это должно занимать всего 1 бит на элемент массива. Однако, согласно документам java. https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html
В реализации виртуальной машины Java Oracle логические массивы на языке программирования Java кодируются как массивы байтов виртуальной машины Java, используя 8 бит на логический элемент.
В этом случае для каждого логического элемента требуется 8 бит. (Это просто для аргументации, и мы не можем использовать логическое значение, так как в нем есть только true и false)
Следующий вариант-использовать логический тип в штучной упаковке. Он может содержать значения true,false и null
Вы можете нанести его на карту следующим образом,
true => 1,
false => -1,
null => 0
и реализуйте это так,
Boolean[][] board = new Boolean[3][3];
board[0][0] = null;
board[0][1] = false;
board[1][0] = true;
Как бы то ни было, оказывается, что логический коробочный тип занимает 128 бит в памяти.(https://www.baeldung.com/java-primitives-vs-objects)
Если вы создадите пользовательский класс, он также займет больше памяти. Поэтому лучше использовать тип байта, как показано ниже, для вашего массива, как и большинство предложенных.
byte[][] board = new byte[3][3];
board[0][0] = -1;
board[0][1] = 0;
board[1][0] = 1;
Ответ №2:
Примечание: Я не говорю, что это хорошая идея. Но…
Существует только 3^9 = 19683 возможных состояний всей доски крестиков-ноликов. Вы можете легко уместить это в одном int
. В качестве примера того, как это сделать, посмотрите на это в двоичном формате и рассмотрите каждую пару битов как одну ячейку:
private int state = 0b00_00_00_00_00_00_00_00_00;
Где мы можем использовать 00
как unset, 10
как X и 11
как O ( 01
не указано, но тоже называйте его unset, таким образом, он не установлен, если есть старший бит 0
).
Затем мы можем получить/установить значение, просто переместив значение в соответствующие биты нашего state
. В этом случае: ( 3 * row ) col
(для пронумерования ячеек платы), а затем *2
, поскольку мы используем 2 бита для каждой ячейки.
public static final int UNSET = 0b00;
public static final int X = 0b10;
public static final int O = 0b11;
public void set( final int row, final int col, final int val ) {
state |= ( val << index( row, col ) );
}
public int get( final int row, final int col ) {
return 0b11 amp; ( state >>> index( row, col ) );
}
private static final int index( final int row, final int col ) {
return 2 * ( ( 3 * row ) col );
}
Где мы используем ИЛИ для установки значений в определенных битах, а также используем И для маскировки результата до двух битов, которые нас интересуют. Здесь, вероятно , была бы полезна некоторая проверка (проверьте row
и col
находятся в пределах, проверьте val
между 0b00
и 0b11
, проверьте, что ячейка не установлена перед настройкой, что угодно еще).
С этим, затем скажите, что первый игрок идет посередине (с X), ваше состояние будет:
state = 0b00_00_00_00_10_00_00_00_00_00;
Затем следующий игрок идет слева вверху с буквой «О».:
state = 0b00_00_00_00_10_00_00_00_00_11;
и т.д.
Опять же, я не говорю, что это хорошая идея, или будет быстрее для вас, или понятнее для людей, быстро читающих код… Но он сохранит всю доску в одном int, а не в их массиве :пожать плечами:.
Комментарии:
1. Примечание: вы можете сделать это с помощью троичной системы и сохранить ее в a
short
. Но без дополнительной работы по считыванию значения (либо рекурсивным делением, либо последовательностью из 8 вычитаний) Я подозреваю, что это будет медленнее, так как шаг «сдвиг бита для получения» будет намного сложнее (нет оператора «сдвиг трит»).