Найти в Дзене
ZDG

Пишу игру Robots на JavaScript и Python. Часть 3: Инициализация

Предыдущие части: Функции и библиотеки, Проектирование

Когда я проектировал игру, то решил, что все игровые сущности будут храниться в массиве размером 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], то есть именно как двумерная матрица с координатами, но это не двумерный массив, а массив массивов. Есть разница и в создании, и в использовании. Сейчас я не буду использовать его, мне удобнее будет работать с адресами в одномерном массиве.

Похоже, что объем этого выпуска распухает, поэтому подведу итоги:

  1. Я использовал константы для хранения чисел, обозначающих мои игровые сущности
  2. Я создал массив размером 22*22 элемента, в котором заранее поставил стенки

Дальше нужно:

  1. Расставить в моем массиве случайным образом роботов, трансформаторы и игрока
  2. Отобразить всё это дело на экране.

Читайте дальше: Расстановка объектов