Предыдущие части: Инициализация, Функции и библиотеки, Проектирование
В предыдущей части я подготовил пустое поле 22*22 со стенками по краям. Теперь я должен расставить в нём роботов, препятствия и игрока.
Сколько их должно быть? Ну пусть пока роботов будет 10, а препятствий 5. Игрок, конечно, один.
Чтобы создать хотя бы одного робота, для начала мне нужно получить случайные координаты X и Y. Роботы не должны попасть на стенки, поэтому диапазон координат будет не 0-21, а 1-20.
На Python:
x = randint(1, 20)
y = randint(1, 20)
На JavaScript:
var x = Math.floor(1 + Math.random() * 19);
var y = Math.floor(1 + Math.random() * 19);
Я сразу встречаю некоторое неудобство: получение случайного числа на JavaScript выглядит слишком громоздко. Это всё потому, что в JavaScript нет функции получения целого случайного числа, как в Питоне. Но... я могу её написать!
Да, когда я говорил про функции языка, речь шла о тех функциях, которые уже есть. Но можно писать и собственные функции, которыми можно точно так же пользоваться. Сейчас я это сделаю:
Что произошло: я создал функцию с именем randint. В круглых скобках в функцию передаются два числа: минимальное и максимальное (min, max). Замечу, это не сами числа, а как бы коробочки с названиями min и maх, куда будут положены реальные числа при вызове функции. Тело функции находится между фигурными скобками "{" и "}". В этом теле вычисляется случайное число на основе min и max и возвращается мне с помощью инструкции return. Теперь я могу вызывать эту функцию когда захочу:
var x = randint(1, 20);
И теперь всё выглядит и работает точно так же, как в Питоне. Что делает транслятор языка:
"Переменной x присваивается значение randint(1, 20). Это выглядит как функция. В языке нет такой функции, но я вижу, что программист сам написал её. Я также вижу, что туда надо передать два числа, которые называются min и max. Программист написал 1, 20, значит я передам 1 как min и 20 как max."
Что делает функция:
"Мне должны передать min и мах. Я вижу, что передали 1 и 20, значит min это 1, а max это 20. У меня тут записано: min + Math.random() * (max - min), значит получается так: 1 + Math.random() * (20-1). Всё, можно это дело вычислить и вернуть."
Вычислив случайные координаты x и y, я преобразую их в адрес внутри массива, и запишу по этому адресу константу ROBOT. Всё, я поставил робота в клетку!
на Питоне:
на JavaScript:
Как я вычисляю адрес? Элементарно. Так как массив у меня размером 22*22, то через каждые 22 элемента начинается новая строка. Y*22 указывает на адрес начала строки с номером Y, к которому прибавляется координата X.
Можно написать всё и в одну строчку, не создавая лишних переменных. Это сделает код более эффективным, но менее читабельным:
field[randint(1, 20) * 22 + randint(1, 20)] = ROBOT
Хорошо, но мне нужно 10 роботов. Могу ли я написать вот так?
Несомненно, я могу так написать. Повторив одну строчку 10 раз, я создам 10 роботов. Но так сделал бы программист, который не знает о циклах. А я лучше напишу цикл:
На JavaScript:
На Питоне:
Циклы выглядят по-разному, но делают одно и то же. Разберем по частям: цикл for в Javascript имеет три параметра, указанные в круглых скобках:
- с чего начать: var i = 0;
- при каких условиях повторять: i < 10;
- что делать в каждом повторении: i++
Развернем это человеческим языком:
- перед началом цикла надо завести переменную i и присвоить ей 0;
- цикл надо повторять, пока i < 10;
- при каждом повторении цикла нужно увеличить i на 1.
Ключевым здесь является третий пункт. Так как при каждом повторении i увеличивается на 1, то цикл отработает ровно 10 раз.
Cамо тела цикла находится между фигурными скобками "{" и "}". Все инструкции, которые там написаны, будут повторены столько раз, сколько раз выполнится цикл.
На Питоне всё несколько иначе:
for i in range(10) значит уже почти человеческим языком:
"для i в пределах 10" (включая 0, но не включая 10, не спрашивайте пока об этом :)
То есть фактически мы просто сообщили, что нам нужно 10 повторений, а транслятор языка Питон сам присвоит i=0 в начале, сам будет прибавлять единицу к i и сам будет проверять, чтобы i было меньше 10.
А тело цикла записано без фигурных скобок, но каждая строчка сдвинута вправо на одинаковое расстояние. Так Python определяет, что это отдельный блок кода (тоже не спрашивайте). Короче говоря, в цикле повторится всё, что сдвинуто вправо относительно первой строчки for.
Ну вот, я создал 10 роботов. Но нужно ещё создать 5 препятствий. Проблем нет – координаты вычисляются так же, цикл повторяется 5 раз, только нужно записывать в массив не константу ROBOT, а константу HAZARD.
Тут я вдруг замечаю, что имею два одинаковых цикла, только с разным числом повторений и с разными константами. Может быть, я напишу функцию, которая будет делать цикл для меня? Я передам в функцию 2 числа: сколько раз повторить и какую константу записать.
Как это делается на JavaScript, мы уже в курсе. Замечу, что эта функция ничего не возвращает в ответ, так тоже можно.
Теперь посмотрим, как сделать функцию в Питоне:
Всё. Функция в Питоне задается не словом function, а словом def (define). Дальше вы можете догадаться – тело функции ограничено не фигурными скобками, а отступом. Тело цикла внутри функции также имеет свой отступ.
Наконец, запишу финальный код генерации 10 роботов и 5 препятствий:
Нужно ещё поставить на поле игрока. Это однократное действие, поэтому ему не нужен ни цикл, ни функция:
Отмечу, что я отдельно сохранил адрес игрока в переменной player_addr, потому что мне нужно будет постоянно с ней работать.
Всё, я получил полностью готовое игровое состояние: в памяти сейчас лежит поле со стенками, роботами, препятствиями и игроком.
Следующим этапом нужно будет отобразить это всё на экране.
Вот пока что полный текущий код на Python и на JavaScript. (Вставить не удалось, не помещается).
Читайте дальше: Графический контекст