Предыдущие части: Функции и библиотеки, Проектирование
Когда я проектировал игру, то решил, что все игровые сущности будут храниться в массиве размером 22*22 элемента и обозначаться так:
0 – пустая клетка
10 – стена
20 – игрок
30 – робот
40 – опасность (трансформатор)
В ходе реализации игры мне придется проверять, что находится в клетках, то есть сравнивать содержимое клеток с этими числами, и делать это неоднократно. Если вдруг по каким-то причинам я захочу, чтобы робот был не 30, а 35, то мне придется в тексте программы все числа 30 исправить на 35. Это неудобно и опасно, так как я могу где-то что-то забыть, или исправить не то число, или сделать опечатку в одном из чисел.
Поэтому, недолго думая, я ввожу константы. Константы – специальные переменные, которым можно присвоить значение один раз и менять затем нельзя. Константы принято записывать большими буквами, чтобы отличать от обычных переменных.
JavaScript:
const W = 10;
const PLAYER = 20;
const ROBOT = 30;
const HAZARD = 40;
В Питоне, кстати, такого понятия нет, поэтому я там создам обычные переменные и сам с собой договорюсь их не менять:
Python:
W = 10
PLAYER = 20
ROBOT = 30
HAZARD = 40
Для пустой клетки я не буду задавать константу. Ноль есть ноль, он сам по себе константа, и вряд ли изменится. Теперь я могу вместо чисел писать константы. Транслятор языка будет видеть эти константы и подставлять вместо них числа. А если я захочу поменять число робота на 35, это достаточно будет сделать только один раз, переписав константу ROBOT.
Перейду к созданию массива 22*22 элемента.
Массив можно создать разными способами, в том числе динамически, добавляя к пустому массиву по одному элементу. Но для простоты и наглядности я сделаю вот так на Python:
На JavaScript это выглядит практически идентично:
Я не просто создал массив, но и сразу вписал в него стенки по периметру, потому что они будут там всегда. (Как можно заметить, я выбрал для стены константу W, а не WALL, просто чтобы квадрат выглядел ровно :)
Итак, я поместил массив с заранее заданными элементами в переменную с именем field. Что произошло на самом деле: транслятор языка увидел, что я создаю массив, и автоматически выделил в памяти кусок размером 484 байта. В этот кусок он перенес все числа, которые я написал через запятую, в том же порядке, в котором я их записал. Потом он взял адрес, c которого начинается этот кусок, и поместил его в переменную field. Теперь он знает, что field – это массив, и знает, в каком месте памяти он находится.
Доступ к элементам массива происходит через смещения от начала его памяти (начиная с 0, конечно). Чтобы получить первый элемент массива, нужно написать field[0]. Транслятор видит такую запись и поступает так:
"Вижу квадратные скобки, значит field это начало массива, а в скобках написано, на сколько элементов нужно сместиться от начала (на 0). Я беру адрес массива из field и смещаюсь от него на 0 элементов. Я теперь могу узнать, что хранится в полученной ячейке памяти."
Через это мы получили первый элемент массива в самом начале его куска памяти. Если мы напишем field[1], транслятор вычислит это как второй элемент массива (адрес массива + 1), field[2] – как третий (адрес массива + 2) и т.д.
Теперь такое дело: Я нарисовал квадратный массив, то есть матрицу, потому что у меня квадратное поле 22*22 клетки. Но в памяти нельзя хранить квадратный массив. Это просто область памяти, она не имеет формы, высоты или ширины, только длину. И второй момент: если каждый объект на поле имеет координаты X и Y, то как мне работать с массивом, у которого есть только смещение от начала и нет никаких X и Y?
Во-первых, записать массив в тексте программы я могу как угодно. Это одна цепочка чисел, но в тексте программы я могу делать переносы строк как мне захочется. Также не имеют значения пробелы, отступы и пустые строки. Транслятор всё равно всегда склеит это в одну и ту же цепочку байт в памяти.
Второй ответ следует из первого. Любую двумерную, трехмерную, N-мерную матрицу можно записать в память как одномерный массив, просто соединив её строки подряд.
Измерения матрицы, её высота и ширина, существуют только в нашем воображении. То же самое касается координат X и Y в матрице. Так как любые координаты соответствуют какой-то одной клетке, а у клетки есть адрес, это значит, что любые координаты можно перевести в адрес, и наоборот.
И в Python, и в JavaScript есть запись вида field[x][y], то есть именно как двумерная матрица с координатами, но это не двумерный массив, а массив массивов. Есть разница и в создании, и в использовании. Сейчас я не буду использовать его, мне удобнее будет работать с адресами в одномерном массиве.
Похоже, что объем этого выпуска распухает, поэтому подведу итоги:
- Я использовал константы для хранения чисел, обозначающих мои игровые сущности
- Я создал массив размером 22*22 элемента, в котором заранее поставил стенки
Дальше нужно:
- Расставить в моем массиве случайным образом роботов, трансформаторы и игрока
- Отобразить всё это дело на экране.
Читайте дальше: Расстановка объектов