Главная » Статьи » Играем Blitz » Общее |
Сначала - о двоичном исчислением, для тех кто с ним не знаком. В обычной, десятичной системе счисления, которую мы используем, для записи чисел используются десять знаков - 0123456789. Любое число можно разложить на разряды следующим образом: a * 10n + b * 10n-1 + ... + x * 102 + y * 10 + z. Например: 956 = 9 * 102 + 5 * 101 + 6 * 100. Число 10 называется ОСНОВАНИЕМ системы. Двоичная система счисления имеет основание 2, то есть любое чило может быть представлено так: a * 2n + b * 2n-1 + ... + x * 22 + y * 2 + z, например: 1011 = 1*23 + 0 * 22 + 1 * 21 + 1 * 20. Легко посчитать, что в десятичной системе счисления это число равно 8 + 2 + 1 = 11. Для записи чисел в двоичной системе счисления используются два знака - 0 и 1. Классические формулы логики оперируют переменными только с двумя значениями - ИСТИНА (1) и ЛОЖЬ (0):
Логические операции над числами (которые имеют 32 бита) можно представить, так:
Умножение и делениеКоманды "a SHL n" и "a SHR n" осуществляют побитовый сдвиг в числе a на n бит. SHR - вправо, SHL - влево. Скажем, 43(101011) SHR 1 = 21(10101), 5(101) SHL 3 = 40(101000). Как видите, SHR уничтожает значения крайних битов, а SHL дополняет число нулями. Нижеследующие эквиваленты очень полезны, т. к. логические операции гораздо быстрее арифметических, пытайтесь по возможности максимально широко использовать логические.
ЗацикливаниеОчень часто в программе требуется "зациклить" какую-нибудь переменную. Например, игрок с координатами (X, Y) находится на карте NxN клеток, где каждая клетка имеет координаты (0...n-1, 0...n-1). Он может перемещаться вверх / вниз / вправо / влево, соответвственно меняются координаты (Y = Y - 1 / Y = Y + 1 / X = X + 1 / X = X - 1). Необходимо сделать так, чтобы при выходе за пределы карты, он появлялся с другой стороны, то есть, если координата X равна 0, а игрок делает шаг влево, то она становится равной не -1, а n-1 (противоположный край карты). Все бы ничего, да на карте есть локация с сапогами-скороходами, позволяющими перемещаться в любую сторону на случайное расстояние, которое может быть в несколько раз больше n. Соответственно, надо учитывать, что игрок может "промотать" за один ход несколько кругов по карте, в том числе и уменьшая координату. Самый простой (и самый медленный) способ выглядит так: ;Функция уменьшает или увеличивает переменную на n, пока она не окажется в
;пределах (0...n - 1) Хорошо, если это только один игрок, а если это подконтрольные компьютеру существа, которых тысячи? Еще пара способов, более скоростных: ;Этот способ использует остаток от деления на n. Число "5" означает максимальное
;количество кругов, которое переменная может "промотать" назад. Но самый быстрый способ можно применить, если n = 2m (m >= 1), тогда: Вот и все! Но давайте разберемся, как это работает. Число 2m в двоичной системе счисления выглядит так: 1000...0, где нулей ровно m. А если от него отнять единицу, то получим число 1111...1, в котором будет m единиц. Операция AND отсекает ненужные биты, образующиеся при выходе переменной за рамки (0...n - 1). Например, n AND (n - 1) = 0, а -1(11111...11111 - 32 единицы) AND (n - 1) = n - 1, что, собственно, и требовалось. Упаковка данныхА вот проблема, возникающая при работе с большими картами во многих типах программ: приходится к каждой клетке большой карты привязывать несколько параметров. Ну, например, создается мега-аркада с огромной картой, 1000 на 1000 клеток. Каждая клетка содержит следующую информацию: номер тайла (изображения клетки) (0-999), проходимость (0 - да, 1 - нет), 2 дополнительных изображения (следы крови, сажа) в диапазоне от 0 до 59, уровень заполненности водой (0-15), предмет (0-11). Если идти стандартным путем, то для хранения всей этой информации понадобится 6 массивов, и вся карта будет занимать 28MB. Может показаться, что трата памяти сейчас практически не проблема, но если карта представляет огромный мир и в несколько десятков раз больше? Сколько будут занимать и загружаться сохраненные игры? Есть способ свести данные в один массив, то есть уменьшить их объем в 7 раз в данном случае. Для начала, попробуем определить, сколько бит занимает каждая из составляющих:
Теперь разобъем биты переменной на части:
Теперь можно работать с массивом: ;Если все составляющие известны, то формируется массив следующим образом:
; каждая переменная сдвигается на свою позицию, и все они складываются В программе реализации игры "Жизнь" такая упаковка данных еще и ускоряет работу. Упрощение формулВот, например одна из часто возникающих задач: переменная A принимает определенные значения (1, 3, 9, 10, 15), переменная B, в зависимости от того, какое значение приняла первая, должна принять значение из другого набора (2, 6, 3, 5, 11). К примеру, если A=1, то B=2, если A=3, то B=6. Самый простой и наглядный способ - это использовать оператор SELECT: Еще один способ - более медленный и менее наглядный, но компактен и позволяет присваивать значения строковым переменным: Способ, использующий логические выражения, нагляден и компактен, но уступает первым двум по скорости: B=(A=1)*2+(A=3)*9+(A=9)*3+(A=10)*5+(A=15)*11
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Просмотров: 94 | |
Всего комментариев: 0 | |