Задание 8 Настала очередь конструктора класса Snake. Змея у нас будет поначалу состоять из одного кусочка - головы. А что для него требуется? Что необходимо передать в конструктор? Координаты змеи, конечно же. Надо: а) Передать в конструктор координаты головы змеи (x и y) б) создать в нем первый "кусочек змеи" (голову) и добавить его в коллекцию sections. в) isAlive выставить в true г) не забудь в конструкторе инициализировать переменную sections. В null не много-то и добавишь! д) создать и реализовать метод int getX(). Метод должен вернуть координату Х головы змеи. е) создать и реализовать метод int getY(). Метод должен вернуть координату Y головы змеи. ё) еще добавить классу метод move()- он нам пригодится попозже.
package com.javarush.test.level23.lesson13.big01; import java.util.ArrayList; /** * Created by promoscow on 22.01.17. */ public class Snake { private ArrayList<SnakeSection> sections; private boolean isAlive; private SnakeDirection direction; public ArrayList<SnakeSection> getSections() { return sections; } public boolean isAlive() { return isAlive; } public SnakeDirection getDirection() { return direction; } public void setDirection(SnakeDirection direction) { this.direction = direction; } public int getX(int x) { return sections.get(0).getX(); } public int getY(int y) { return sections.get(0).getY(); } public Snake(int x, int y) { sections = new ArrayList<>(); sections.add(new SnakeSection(x, y)); isAlive = true; } public void move() { } }
Задание 9 Еще остался самый главный класс - Room. Что нам нужно для его описания? Размеры комнаты (width и height) - раз. Змея - два Мышь - три. Надо: а) создать в классе Room переменные width & height типа int. б) создать в классе Room переменную snake типа Snake. в) создать в классе Room переменную mouse типа Snake. Шучу. Типа Mouse, конечно же 🙂 г) создать для них всех геттеры и сеттеры. д) создать конструктор. Конструктор должен принимать три параметра: width, height и ... snake!
package com.javarush.test.level23.lesson13.big01; /** * Created by promoscow on 22.01.17. */ public class Room { private int width; private int height; private Snake snake; private Mouse mouse; public Room(int width, int height, Snake snake) { this.width = width; this.height = height; this.snake = snake; } public void setWidth(int width) { this.width = width; } public void setHeight(int height) { this.height = height; } public void setSnake(Snake snake) { this.snake = snake; } public void setMouse(Mouse mouse) { this.mouse = mouse; } public int getWidth() { return width; } public int getHeight() { return height; } public Snake getSnake() { return snake; } public Mouse getMouse() { return mouse; } public static void main(String[] args) { } }
Задание 10 Займемся методом main. Для начала надо создать статическую переменную game типа Room. Доступ к переменной должен быть для всех классов. Затем в методе main: а) Создать змею - объект Snake б) Создать комнату - объект типа Room и передать в него ширину, высоту и змею. в) Установить змее direction равным SnakeDirection.DOWN Чего еще не хватает? Собственно метода, в котором будет идти вся игровая логика. И еще нужен метод, который бы отрисовывал все это на экране. а) создать метод run() б) создать метод print()
public static void main(String[] args) { game = new Room(10, 10, new Snake(5, 5)); game.snake.setDirection(SnakeDirection.DOWN); }
Задание 11 Теперь логика управления мышью. С мышью у нас будут происходить две вещи. Первая - змея съест мышь. Вторая - появляется новая мышь в случайной точке комнаты. Надо написать и реализовать метод createMouse() в классе Room. В этом методе мы просто должны создавать новую мышь со случайными координатами в комнате. Как получить случайные координаты? Это ты уже должен был знать. На всякий случай даю подсказку: int x = (int) (Math.random() * width); Еще понадобится метод - eatMouse(), на случай, если мышь все-таки кто-то съест 🙂 Пока сложной логики в этом методе не будет - просто будем вызывать метод createMouse и все.
public void createMouse() { int x = (int) (Math.random() * width); int y = (int) (Math.random() * height); mouse = new Mouse(x, y); } public void eatMouse() { createMouse(); }
Задание 12 Добавить в метод main: в) вызов метода createMouse(). Змея-то у нас есть, пусть и мышь будет г) вызов метода run(). Без него ничего работать не будет. В нем вся основная логика. Неплохо получилось, но я все-таки внесу пару правок. Кстати, как насчет написать метод sleep? Ты уже понял из предыдущих задач, что в методе run нужна пауза. Но насколько я помню, скорость в змейке должна расти при росте ее длины. Значит чем длиннее змея, тем выше скорость и меньше пауза.
public static void main(String[] args) { game = new Room(10, 10, new Snake(5, 5)); game.snake.setDirection(SnakeDirection.DOWN); game.createMouse(); game.run(); }
Задание 13 Предлагаю тебе в этот раз написать специальный метод sleep(). Который будет делать паузу в зависимости от длины змеи (количества элементов в sections). Придумай какой-нибудь хитрый алгоритм. Чтобы на первом уровне пауза была 500 миллисекунд, а к 10 уровню постепенно уменьшилась до 300. И ниже 200 не опускалась.
/** * Прогрмма делает паузу, длинна которой зависит от длинны змеи. */ public void sleep() { try { int pause = 500 - ((snake.getSections().size() - 1) * (200 / 9)); if (pause < 200) pause = 200; Thread.sleep(pause); } catch (InterruptedException e) { e.printStackTrace(); } }
Задание 14 Теперь поработаем над методом print(). Надо: а) вывести на экран прямоугольник из точек размером width x height. б) тело змеи отметить символом "x"-английское в) голову змеи нарисовать символом X-английское. Подсказка: а) удобно сначала создать матрицу типа int[][] с размером (height x width) б) затем пройтись по всем объектам и отрисовать их в матрицу. Например, тело змеи - 1, голова змеи - 2, мышь - 3.
/** * Выводим на экран текущее состояние игры */ public void print() { //Создаем массив, куда будем "рисовать" текущее состояние игры //Рисуем все кусочки змеи //Рисуем мышь //Выводим все это на экран int[][] matrix = new int[height][width]; matrix[snake.getSections().get(0).getY()][snake.getSections().get(0).getX()] = 2; for (int i = 1; i < snake.getSections().size(); i++) { matrix[snake.getSections().get(i).getY()][snake.getSections().get(i).getX()] = 1; } matrix[mouse.getY()][mouse.getX()] = 3; for (int i = 0; i < matrix.length; i++) { for (int j = 0; j < matrix[i].length; j++) { if (matrix[i][j] == 1) System.out.print(" x "); else if (matrix[i][j] == 2) System.out.print(" X "); else if (matrix[i][j] == 3) System.out.print(" * "); else if (matrix[i][j] == 0) System.out.print(" . "); } } }
Задание 15 Теперь осталось допилить змею. Вот что я предлагаю насчет движения змеи: Змея состоит из кусочков. Давай каждый ход просто добавлять один кусочек со стороны головы, а самый последний - удалять. Тогда получится, что змея ползет. Добавлять кусочек нужно рядом с текущей головой (кусочком номер 0). С какой стороны добавлять зависит от direction (UP, DOWN, LEFT, RIGHT). Подсказка: а) Как добавить кусочек змеи в начало списка sections? sections.add(0, new_section); б) А как удалить последний? sections.remove(sections.size()-1); В методе move надо: а) сделать шаг в текущем направлении (определяется direction) б) проверить, что если змея уперлась в стену, то умереть (isAlive = false) в) проверить, что если змея уперлась себя, то умереть (isAlive = false) г) проверить, если змея встретила мышь - то съесть ее.
public void move() { if (direction == SnakeDirection.UP) { sections.add(0, new SnakeSection(sections.get(0).getY() - 1, sections.get(0).getX())); } else if (direction == SnakeDirection.DOWN) { sections.add(0, new SnakeSection(sections.get(0).getY() + 1, sections.get(0).getX())); } else if (direction == SnakeDirection.LEFT) { sections.add(0, new SnakeSection(sections.get(0).getY(), sections.get(0).getX() - 1)); } else if (direction == SnakeDirection.RIGHT) { sections.add(0, new SnakeSection(sections.get(0).getY(), sections.get(0).getX() + 1)); } sections.remove(sections.size()-1); if (sections.get(0).getY() > Room.game.getHeight() - 1 || sections.get(0).getY() < 0 || sections.get(0).getX() > Room.game.getWidth() - 1 || sections.get(0).getX() < 0) isAlive = false; for (SnakeSection section : sections) { if (sections.get(0).getX() == section.getX() && sections.get(0).getY() == section.getY()) isAlive = false; } if (sections.get(0).getY() == Room.game.getMouse().getY() && sections.get(0).getX() == Room.game.getMouse().getX()) Room.game.eatMouse(); } }
Задание 16 Продолжаем работать над методом move() Для определения, не пересекается ли змея сама с собой, можно сделать очень простую проверку: содержит ли список sections "новую голову змеи". Код для этого будет выглядеть примерно так: if (sections.contains(head)) При этом head должен быть еще не добавлен в список sections, иначе будет всегда true. Но чтобы этот код работал, надо реализовать методы сравнения объектов (equals & hashCode) в классе SnakeSection. Задание: а) реализовать методы equals & hashCode в классе SnakeSection. Сигнатура методов: public boolean equals(Object o) public int hashCode() Подсказка: Используй Alt+Insert в Intellij IDEA В классе Snake: б) в методе move(int dx, int dy) создать голову(кусочек змеи) с правильными координатами. Вызвать метод checkBody() и checkBorders() в) реализовать метод checkBody: если голова змеи пересекается с ее телом (любым из кусочков) - змея умирает (isAlive = false)
/** * Метод перемещает змею на один ход. * Направление перемещения задано переменной direction. */ public void move() { if (!isAlive) return; if (direction == SnakeDirection.UP) move(0, -1); else if (direction == SnakeDirection.RIGHT) move(1, 0); else if (direction == SnakeDirection.DOWN) move(0, 1); else if (direction == SnakeDirection.LEFT) move(-1, 0); } /** * Метод перемещает змею в соседнюю клетку. * Кординаты клетки заданы относительно текущей головы с помощью переменных (dx, dy). */ private void move(int dx, int dy) { //Создаем новую голову - новый "кусочек змеи". //Проверяем - не вылезла ли голова за границу комнаты //Проверяем - не пересекает ли змея саму себя //Проверяем - не съела ли змея мышь. //Двигаем змею. SnakeSection head = new SnakeSection(dx, dy); checkBody(head); checkBorders(head); } /** * Метод проверяет - находится ли новая голова в пределах комнаты */ private void checkBorders(SnakeSection head) { if (head.getY() > Room.game.getHeight() - 1 || head.getY() < 0 || head.getX() > Room.game.getWidth() - 1 || head.getX() < 0) isAlive = false; } /** * Метод проверяет - не совпадает ли голова с каким-нибудь участком тела змеи. */ private void checkBody(SnakeSection head) { if (sections.contains(head)) isAlive = false; }
Задание 17 Теперь закончим класс Shake Надо: а) реализовать метод checkBorders: если голова змеи за границами комнаты - змея умирает (isAlive = false) Реализовать метод move(int dx, int dy): б) проверить, не вылезла ли она за границу комнаты (если да, то змея умирает) в) проверить, не совпадает ли она с уже существующими кусочками змеи (если да, то змея умирает) г) добавить голову к змее (со стороны головы) и удалить последний кусочек из хвоста. д) если змея поймала мышь (координаты головы совпадают с координатами мыши), то удалять кусок из хвоста не надо.
/** * Метод перемещает змею на один ход. * Направление перемещения задано переменной direction. */ public void move() { if (!isAlive) return; if (direction == SnakeDirection.UP) move(0, -1); else if (direction == SnakeDirection.RIGHT) move(1, 0); else if (direction == SnakeDirection.DOWN) move(0, 1); else if (direction == SnakeDirection.LEFT) move(-1, 0); } /** * Метод перемещает змею в соседнюю клетку. * Кординаты клетки заданы относительно текущей головы с помощью переменных (dx, dy). */ private void move(int dx, int dy) { //Создаем новую голову - новый "кусочек змеи". //Проверяем - не вылезла ли голова за границу комнаты //Проверяем - не пересекает ли змея саму себя //Проверяем - не съела ли змея мышь. //Двигаем змею. SnakeSection head = new SnakeSection(sections.get(0).getX() + dx, sections.get(0).getY() + dy); //создаём новую секцию head checkBody(head); //проверяем, не втыкается ли она в себя checkBorders(head); //проверяем, не втыкается ли она в борт sections.add(0, head); if (head.getY() == Room.game.getMouse().getY() && head.getX() == Room.game.getMouse().getX()) { Room.game.eatMouse(); } else sections.remove(sections.size()-1); } /** * Метод проверяет - находится ли новая голова в пределах комнаты */ private void checkBorders(SnakeSection head) { if (head.getY() >= Room.game.getHeight() || head.getY() < 0 || head.getX() >= Room.game.getWidth() || head.getX() < 0) isAlive = false; } /** * Метод проверяет - не совпадает ли голова с каким-нибудь участком тела змеи. */ private void checkBody(SnakeSection head) { if (sections.contains(head)) isAlive = false; }
Leave A Comment