Могу ли я создать мини-класс int, состоящий только из 1, 0, -1?

#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 вычитаний) Я подозреваю, что это будет медленнее, так как шаг «сдвиг бита для получения» будет намного сложнее (нет оператора «сдвиг трит»).