Задание 31. Змейка и Мухоморы: начало
Общее описание игры здесь. Вторая часть игры условие. Третья часть здесь.
Коротко про классы в Java. (пишите/говорите мне, если еще что-то надо описать, или что-то описано плохо/поверхностно)
Дедлайны:
- 9-1: 31 января
- 10-1: 21 января
- 11-1: 21 января
P.S. сдавать это задание можно и после дедлайна - вместе со второй частью (отрисовка), но балл будет снижен. При сдаче вместе с третьей частью максимальное что можно получить - 3.
Создайте пустой проект в IDEA
- File->New->Project
- Сверху слева должна быть выбрана Java, сверху должен быть выбран какой-нибудь Project SDK (по умолчанию все выбрано правильно),
Next - Поставить галку на
Create project from templateи выбратьCommand Line App,Next - Укажите папку для проекта (убедитесь, что у вас есть права на запись в эту папку), и в
Base packageнапишитеcom.snake,Finish - Если появилось окошко - прочитайте что оно пишет, скорее всего оно спрашивает где открыть созданный проект - в запущенном окне IDEA или в новом окне (жмите на ваше усмотрение)
1) Режим Packages

Слева у вас окно обзора проекта (Project View) (вызывается горячей кнопкой Alt+1 и Alt+F1 -> 1).
Вы можете выбрать, что там показывается:
Project- файлы проекта и библиотеки-зависимости (удобно, когда важны в т.ч. файлы, не являющиеся исходниками)Packages- только исходники в пакетах и библиотеки-зависимости (удобно когда нужно только кодить, советую этот вариант)

В режиме Packages вы видите только исходники, разложенные по папкам-пакетам:
- В Java действует правило
один файл - один класс, поэтому взглянув на эти файлы уже видны основные сущности проекта - Эти классы лежат в специальных папках, которые в Java называются пакеты (packages), обычно это что-то вроде com.projectname.some.long.subnames
-
com.snake.logic- классы ответственные за описание логики:- класс
Direction- “направление движения” (на самом деле это специфический класс -Enum) - класс
Snake- описание Змейки - класс
TilePosition- “координата клетки” - класс
World- описание Мира
- класс
-
com.snake.gui- классы ответственные за отрисовку:- класс
MainFrame- Java окно - класс
Renderer- ответственен за отрисовку нашей игры - класс
UpdateLoop- ответственен за обновление состояния нашей игры
- класс
2) Про пакеты и классы

В каждом файле класса объявлен публичный класс, его название можно увидеть в нескольких местах (слева направо):
- Название класса-файла в
Project View - Название в пути к текущему редактируемому файлу
- Название открытого во вкладке файла
- Название класса в его объявлении
- Название класса, ```public static void main(…)`функция которого будет вызываться
Пакет, в котором класс лежит можно увидеть (слева направо):
- Иерархия пакетов в
Project View - Иерархия в пути к текущему редактируемому файлу
- Объявление в каком пакете должен находиться объявляемый в этом файле класс
3) Создание классов логики нашей игры
Нужно создать четыре класса в пакете com.snake.logic, как на скриншоте выше:
- TilePosition
- Direction
- Snake
- World
3.1) Создание класса TilePosition
Для этого сначала надо создать пакет logic в пакете snake, который лежит в пакете com:
Правой кнопкой по com.snake -> New -> Package -> “logic” -> Ok
Теперь надо создать класс TilePosition:
Правой кнопкой по пакету logic -> New -> Java Class -> Name=”TilePosition”, Kind=Class -> Ok
Теперь описать его, в нем должны быть:
- Два поля: целые числа x и y
- Конструктор от двух целых чисел
- Функция toString, которая будет приятно для глаза печатать x и y

По аналогии с классом Human из старого задания:
- x и y должны быть объявлены как и age, name в верхней части Human (верхний эллипс)
- Конструктор должен быть объявлен как и в Human, но называется он TilePosition (т.к. конструктор всегда называется так же, как и конструируемый им класс) и параметрами в него передаются x и y
- toString тоже очень похож, но он должен выводить координаты в удобном виде, например ввиде
Tile[10, 20](если x=10 и y=20)
3.2) Создание Direction (Enum)
Создается так же, как и класс, за исключением того, что когда вы указываете название класса в выпадающем списке Kind надо выбрать вместо Class - Enum.
Enum - это перечисление (сокращенное от enumeration), в нем можно перечислить направления движения, или виды животных. От вас требуется перечислить четыре направления движения - вверх, вниз, влево, вправо.
Вот пример того, как может быть объявлено перечисление пяти видов животных:
package com.zoo;
public enum Animal {
Cat,
Dog,
Narwhal,
Unicorn,
Bear
}
Пример использования:
Animal myAnimal = Animal.Cat;
if (myAnimal == Animal.Dog) {
System.out.println("Что-то не так, ведь мое животное - кошка, а не собака!");
} else if (myAnimal == Animal.Cat) {
System.out.println("Все верно! Мое животное - кошка!"); // Эта строчка исполнится
} else {
System.out.println("Что-то не так, ведь мое животное - кошка, а не что-то еще!");
}
P.S. это по сути более удобная замена константам вида:
int ANIMAL_CAT = 1;
int ANIMAL_DOG = 2;
...
3.3) Создание класса Snake
Аналогично создается класс Snake в пакете com.snake.logic, но в нем должно быть:
- Поле snakeParts: список элементов цепочки клеток, которые образуют змейку. Удобный класс для этого -
LinkedList. Т.к. каждый элемент в нем - это объект классаTilePosition, то объявление такой переменной имеет видLinkedList<TilePosition> snakeParts - Поле направления движения:
Direction direction - Поле длины змейки - целочисленное
- Конструктор змейки (от
TilePosition head,Direction direction) - создает змейку из одного звена - головы - Метод
eatApple- удлиняет змейку на один сегмент (например можно к звеньям добавить последнее звено еще раз через методыLinkedList.peekLastиLinkedListaddLast) - Метод
makeStep- убирает из звеньев последний элемент (LinkedList.pollLast) и добавляет в начало списка звеньев новую позицию головы (по координатам текущей головы + направление движения)
3.4) Создание класса World
Создается класс World в пакете logic:
Поля:
- Число клеток по горизонтали и вертикали
- Змейка
- Яблоко (
TilePosition)
Конструктор от размера игрового мира (число клеток по обеим осям).
Методы:
- getSnake - возращает змейку
- getWidth, getHeight - возвращают размеры поля
- generateApple - создает новое случайное яблоко в одной из незанятых змейкой клетке
- checkApple - проверяет, а не оказалось ли так, что голова змейки находится в той же клетке, что и яблоко
Обратите внимание, что в checkApple нельзя сравнивать TilePosition с TilePosition как можно было бы сделать с примитивными типами навроде int.
Пример:
if (new TilePosition(1, 2) == new TilePosition(1, 2)) { // логическое выражение всегда false
System.out.println("test1"); // эта ветка никогда не исполнится
} else {
System.out.println("test2"); // всегда выполнится эта ветка кода
}
В таком примере всегда выполнится вторая ветка (логическое выражение всегда false), т.к. оператор == всё кроме примитивных типов сравнивает по адресу в памяти. Т.е. просто сверяет один ли и тот же это объект (не с логической точки зрения, а с точки зрения был ли он создан оператором new в одном и том же месте).
Например в таком коде оператор == вернет true:
TilePosition tile = new TilePosition(1, 2);
if (tile == tile) { // логическое выражение всегда true
System.out.println("test1"); // всегда выполнится эта ветка кода
} else {
System.out.println("test2"); // эта ветка никогда не исполнится
}
В данном случае tile - один и тот же объект с точки зрения создания оператором new (имеет одинаковый адрес в памяти).
Поэтому чтобы сравнить голову змеи и яблоко с точки зрения логического совпадения координат - нужно это сделать более явно, чем через оператор == (например явным сравнением полей объектов - сравнинем x и y).
4) Отправка задания
У вас не должно быть нигде ничего красным подсвечено, т.е. ваш код должен компилироваться. Для убеждения в этом - попробуйте запустить Main класс, который у вас был создан вместе с проектом.
Отправляйте выполненное задание ввиде zip-архива src папки, и пожалуйста:
- Тему письма называйте правильно (номер этого задания, как написано в самом верху - 31)
- zip-архив называйте по тем же правилам, как назывались патчи (только расширение файла теперь не
.patch, а.zip)
Т.е. формат такой же как и про патч, только вместо .patch вы шлете .zip.