Создание проекта и файлов классов игры Змейка
Класс myFrame –это класс окна,который наследуется от класса JFrame. В нем будет подключаться панель окна, на которой расположено игровое поле. Также в этом классе будут указаны все параметры окна:его размеры, заголовок и т.д.
Класс myPanel –это класс панели окна, который наследуется от класса JPanel.Этот класс представляет собой игровое поле. Именно этот класс будет подключаться к окну в классе myFrame. Вся графика (отрисовка игрового поля), настройка таймеров, обработка клавиатуры будет происходить именно в этом классе. Но все данные для отрисовки игрового поля класс myPanelбудет получать из класса game, в котором находиться двумерный массив.
Класс game– это класс для реализации логики игры. В этом классе будет находиться двумерный массив, и все операции с двумерным массивом будут производиться именно в этом классе. Класс myPanel будет постоянно обращаться к классу game, чтобы выполнить отрисовку игрового поля по данным двухмерного массива. Данные массива будут зеркально отображаться на игровом поле в классе myPanel, но сами изменения данных массива будут происходить в классе game.
Такая схема классов, конечно же, не является единственной для создания игры Змейка. Программист сам определяет для себя схему классов и их название.
Алгоритм игры ,использованный при реализации игры Змейка, также не является единственным. Программист может использовать алгоритм по своему усмотрению. На начальном этапе программирования не стоит гнаться за малым объемом программного кода. Главное больше практики! Полный вариант игры Змейка, представленный в данном методическом пособии (если убрать из него пустые строки и комментарии) в сумме будет составлять 250 строк программного кода. С вашим опытом объем программного кода будет уменьшаться!
Одномерные массивы в Java
Объявление массива
Переменную массива можно объявить с помощью квадратных скобок:
int[] cats; // мы объявили переменную массива
Возможна и альтернативная запись:
int cats[]; // другой вариант
Здесь квадратные скобки появляются после имени переменной. В разных языках программирования используются разные способы, и Java позволяет вам использовать тот вариант, к которому вы привыкли. Но большинство предпочитает первый вариант. Сами квадратные скобки своим видом напоминают коробки, поэтому вам будет просто запомнить.
Мы пока только объявили массив, но на самом деле его ещё не существует, так как не заполнен данными. Фактически значение массива равно null.
Определение массива
После объявления переменной массива, можно определить сам массив с помощью ключевого слова new с указанием типа и размера. Например, массив должен состоять из 10 целых чисел:
cats = new int[10];
Можно одновременно объявить переменную и определить массив (в основном так и делают):
int[] cats = new int[10];
Если массив создается таким образом, то всем элементам массива автоматически присваиваются значения по умолчанию. Например, для числовых значений начальное значение будет 0. Для массива типа boolean начальное значение будет равно false, для массива типа char - '\u0000', для массива типа класса (объекты) - null.
Последнее правило может запутать начинающего программиста, который забудет, что строка типа Stringявляется объектом. Если вы объявите массив из десяти символьных строк следующим образом:
String[] catNames = new String[10];
То у вас появятся строки со значением null, а не пустые строки, как вы могли бы подумать. Если же вам действительно нужно создать десять пустых строк, то используйте, например, такой код:
for (int i = 0; i < 10; i++)
catNames[i] = "";
Доступ к элементам массива
Обращение к элементу массива происходит по имени массива, за которым следует значение индекса элемента, заключенного в квадратные скобки. Например, на первый элемент нашего массива cats можно ссылаться как на cats[0], на пятый элемент как cats[4].
В качестве индекса можно использовать числа или выражения, которые создают положительное значение типа int. Поэтому при вычислении выражения с типом long, следует преобразовать результат в int, иначе получите ошибку. С типами short и byte проблем не будет, так как они полностью укладываются в диапазон int.
Инициализация массива
Не всегда нужно иметь значения по умолчанию. вы можете инициализировать массив собственными значениями, когда он объявляется, и определить количество элементов. Вслед за объявлением переменной массива добавьте знак равенства, за которым следует список значений элементов, помещенный в фигурные скобки. В этом случае ключевое слово new не используется:
int[] cats = {2, 5, 7, 8, 3, 0}; // массив из 6 элементов
Можно смешать два способа. Например, если требуется задать явно значения только для некоторых элементов массива, а остальные должные иметь значения по умолчанию.
int[] cats = new int[6]; // массив из шести элементов с начальным значением 0 для каждого элемента
cats[3] = 5; // четвертому элементу присвоено значение 5
cats[5] = 7; // шестому элементу присвоено значение 7
Двумерный массив
Двумерный массив - это массив одномерных массивов. Если вам нужен двумерный массив, то используйте пару квадратных скобок:
String[][] arr = new String[4][3];
arr[0][0] = "1";
arr[0][1] = "Васька";
arr[0][2] = "121987102";
arr[1][0] = "2";
arr[1][1] = "Рыжик";
arr[1][2] = "2819876107";
arr[2][0] = "3";
arr[2][1] = "Барсик";
arr[2][2] = "412345678";
arr[3][0] = "4";
arr[3][1] = "Мурзик";
arr[3][2] = "587654321";
Представляйте двумерный массив как таблицу, где первые скобки отвечают за ряды, а вторые - за колонки таблицы. Тогда пример выше представлят собой таблицу из четырёх рядов и трёх колонок.
Васька | ||
Рыжик | ||
Барсик | ||
Мурзик |
Для двумерных массивов часто используются два цикла for, чтобы заполнить элементы данными слева направо и сверху вниз. Напишем такой код:
int[][] twoD = new int[3][4]; // объявили двухмерный массив
int i, j, k = 0;
for (i = 0; i < 3; i++)
for (j = 0; j < 4; j++) {
twoD[i][j] = k;
k++;
}
for (i = 0; i < 3; i++) {
for (j = 0; j < 4; j++)
mInfoTextView.append(twoD[i][j] + " ");
mInfoTextView.append("\n");
}
В данном примере мы сначала заполнили двумерый массив данными, а затем снова прошлись по этому массиву для считывания данных.
Логическое представление данного двухмерного массива будет выглядеть следующим образом:
[0, 0] | [0, 1] | [0, 2] | [0, 3] |
[1, 0] | [1, 1] | [1, 2] | [1, 3] |
[2, 0] | [2, 1] | [2, 2] | [2, 3] |
Первое число в скобках обозначают ряд (строку), а второе число - столбец. Принято считать, что в массиве new int[M][N] первый размер означает количество строк, а второй - количество столбцов.
На экране после запуска примера мы увидим следующее:
0 1 2 3
4 5 6 7
8 9 10 11
При резервировании памяти под многомерный массив необходимо указать память только для первого измерения. Для остальных измерений память можно выделить отдельно.
int[][] twoD = new int[3][]; // память под первое измерение
// далее резервируем память под второе измерение
twoD[0] = new int[4];
twoD[1] = new int[4];
twoD[2] = new int[4];
В данном примере особого смысла в этом нет.
Еще одна интересная особенность при создании массива связана с запятой. Посмотрите на пример.
int[][] a = {{1, 2, 3}, {4, 0, 0,},};
System.out.println(Arrays.deepToString(a));
Вроде в конце используется лишняя запятая, но её наличие не приведёт к ошибке (только одна запятая). Это бывает удобно, когда надо скопировать или вставить кусок массива в коде. Кстати, метод deepToString() класса Arrays очень удобен для вывода двухмерных массивов.
Чтобы совсем сбить вас с толку, приведу ещё один правильный пример.
Integer[] Integer[] = {{1, 2, 3}, {4, 0, 0,},};
System.out.println(Arrays.deepToString(Integer));
Я уже упоминал, что квадратные скобки можно использовать двумя способами. Сначала мы поставили скобки у типа переменной, а потом у имени переменной. При этом мы использовали в качестве имени имя класса Integer. Однако, Java догадывается, что на этот раз используется не класс, а имя и разрешает такой синтаксис. Но лучше так не выпендриваться.
Размер имеет значение
Размер двумерного массива измеряется интересным способом. Длина массива определяется по его первой размерности, то есть вычисляется количество рядов.
int[][] matrix = new int[4][5];
System.out.println(matrix.length);
А если мы хотим узнать количество столбцов в ряду? Тогда указываете ряд, а затем вычисляете у него количество столбцов.
// число колонок у третьего ряда
System.out.println(matrix[2].length);
Не забывайте, что в массивах ряды могут содержать разное количество столбцов.
Класс Arrays
Класс java.util.Arrays предназначен для работы с массивами. Он содержит удобные методы для работы с целыми массивами:
- copyOf() − предназначен для копирования массива
- copyOfRange() − копирует часть массива
- toString() − позволяет получить все элементы в виде одной строки
- sort() — сортирует массив методом quick sort
- binarySearch() − ищет элемент методом бинарного поиска
- fill() − заполняет массив переданным значением (удобно использовать, если нам необходимо значение по умолчанию для массива)
- equals() − проверяет на идентичность массивы
- deepEquals() − проверяет на идентичность массивы массивов
- asList() − возвращает массив как коллекцию
Подготовка изображений для игры Змейка
Прежде всего, подготовим необходимые изображения, которые понадобятся при создании игры. На этапе разработки можно взять простые изображения, сделанные в любом графическом редакторе и писать программный код с их использованием. Вполне подойдут картинки, найденные в интернете или сделанные самостоятельно. Когда игра будет закончена, можно сделать более внушительный дизайн, заменив исходные варианты картинками такого же размера, но с более привлекательным дизайном. Вспомним, что основной формат при разработке на Java –это формат PNG. Именно в этом формате необходимо подготовить изображения.
Выполнить конвертацию в формат PNG можно во многих графических редакторах.
Для игры Змейка понадобятся пять изображений:
1) Основной фон
2) Объект для поедания Змейкой
3) Голова Змейки
4) Элемент тела Змейки
5) Изображение Конец Игры
Подготовим следующие изображения:
· fon.png (см. рис. 2) –это фоновое изображение, размер 800x650 –размеры окна по условию задания.
Рис. 2
· telo.png (см. рис. 3) –элемент тела Змейки, размер 20x20– размер одной клетки игрового поля по условию задания.
Рис. 3
· golova.png (см. рис. 4) –голова Змейки, размер 20x20 –размер одной клетки игрового поля по условию задания.
Рис. 4
· ob.png (см. рис. 5) –объект для поедания Змейкой, размер 20x20 –размер одной клетки игрового поля по условию задания.
Рис. 5
· endg.png (см. рис. 6) –изображение "Конец Игры", размер 200x100–размер взят произвольно, здесь главное, чтобы рисунок помещался на игровом поле.
Рис. 6
Все пять изображений поместим, например, в корень диска C:\. В процессе разработки игры изображения будут загружаться из корня диска C:\. После окончания создания игры мы поместим их внутрь JAR-архива.
Класс myFrame –это класс окна,который наследуется от класса JFrame. В нем будет подключаться панель окна, на которой расположено игровое поле. Также в этом классе будут указаны все параметры окна:его размеры, заголовок и т.д.
Класс myPanel –это класс панели окна, который наследуется от класса JPanel.Этот класс представляет собой игровое поле. Именно этот класс будет подключаться к окну в классе myFrame. Вся графика (отрисовка игрового поля), настройка таймеров, обработка клавиатуры будет происходить именно в этом классе. Но все данные для отрисовки игрового поля класс myPanelбудет получать из класса game, в котором находиться двумерный массив.
Класс game– это класс для реализации логики игры. В этом классе будет находиться двумерный массив, и все операции с двумерным массивом будут производиться именно в этом классе. Класс myPanel будет постоянно обращаться к классу game, чтобы выполнить отрисовку игрового поля по данным двухмерного массива. Данные массива будут зеркально отображаться на игровом поле в классе myPanel, но сами изменения данных массива будут происходить в классе game.
Такая схема классов, конечно же, не является единственной для создания игры Змейка. Программист сам определяет для себя схему классов и их название.
Алгоритм игры ,использованный при реализации игры Змейка, также не является единственным. Программист может использовать алгоритм по своему усмотрению. На начальном этапе программирования не стоит гнаться за малым объемом программного кода. Главное больше практики! Полный вариант игры Змейка, представленный в данном методическом пособии (если убрать из него пустые строки и комментарии) в сумме будет составлять 250 строк программного кода. С вашим опытом объем программного кода будет уменьшаться!
Одномерные массивы в Java
Объявление массива
Переменную массива можно объявить с помощью квадратных скобок:
int[] cats; // мы объявили переменную массива
Возможна и альтернативная запись:
int cats[]; // другой вариант
Здесь квадратные скобки появляются после имени переменной. В разных языках программирования используются разные способы, и Java позволяет вам использовать тот вариант, к которому вы привыкли. Но большинство предпочитает первый вариант. Сами квадратные скобки своим видом напоминают коробки, поэтому вам будет просто запомнить.
Мы пока только объявили массив, но на самом деле его ещё не существует, так как не заполнен данными. Фактически значение массива равно null.
Определение массива
После объявления переменной массива, можно определить сам массив с помощью ключевого слова new с указанием типа и размера. Например, массив должен состоять из 10 целых чисел:
cats = new int[10];
Можно одновременно объявить переменную и определить массив (в основном так и делают):
int[] cats = new int[10];
Если массив создается таким образом, то всем элементам массива автоматически присваиваются значения по умолчанию. Например, для числовых значений начальное значение будет 0. Для массива типа boolean начальное значение будет равно false, для массива типа char - '\u0000', для массива типа класса (объекты) - null.
Последнее правило может запутать начинающего программиста, который забудет, что строка типа Stringявляется объектом. Если вы объявите массив из десяти символьных строк следующим образом:
String[] catNames = new String[10];
То у вас появятся строки со значением null, а не пустые строки, как вы могли бы подумать. Если же вам действительно нужно создать десять пустых строк, то используйте, например, такой код:
for (int i = 0; i < 10; i++)
catNames[i] = "";
Доступ к элементам массива
Обращение к элементу массива происходит по имени массива, за которым следует значение индекса элемента, заключенного в квадратные скобки. Например, на первый элемент нашего массива cats можно ссылаться как на cats[0], на пятый элемент как cats[4].
В качестве индекса можно использовать числа или выражения, которые создают положительное значение типа int. Поэтому при вычислении выражения с типом long, следует преобразовать результат в int, иначе получите ошибку. С типами short и byte проблем не будет, так как они полностью укладываются в диапазон int.
Инициализация массива
Не всегда нужно иметь значения по умолчанию. вы можете инициализировать массив собственными значениями, когда он объявляется, и определить количество элементов. Вслед за объявлением переменной массива добавьте знак равенства, за которым следует список значений элементов, помещенный в фигурные скобки. В этом случае ключевое слово new не используется:
int[] cats = {2, 5, 7, 8, 3, 0}; // массив из 6 элементов
Можно смешать два способа. Например, если требуется задать явно значения только для некоторых элементов массива, а остальные должные иметь значения по умолчанию.
int[] cats = new int[6]; // массив из шести элементов с начальным значением 0 для каждого элемента
cats[3] = 5; // четвертому элементу присвоено значение 5
cats[5] = 7; // шестому элементу присвоено значение 7
Двумерный массив
Двумерный массив - это массив одномерных массивов. Если вам нужен двумерный массив, то используйте пару квадратных скобок:
String[][] arr = new String[4][3];
arr[0][0] = "1";
arr[0][1] = "Васька";
arr[0][2] = "121987102";
arr[1][0] = "2";
arr[1][1] = "Рыжик";
arr[1][2] = "2819876107";
arr[2][0] = "3";
arr[2][1] = "Барсик";
arr[2][2] = "412345678";
arr[3][0] = "4";
arr[3][1] = "Мурзик";
arr[3][2] = "587654321";
Представляйте двумерный массив как таблицу, где первые скобки отвечают за ряды, а вторые - за колонки таблицы. Тогда пример выше представлят собой таблицу из четырёх рядов и трёх колонок.
Васька | ||
Рыжик | ||
Барсик | ||
Мурзик |
Для двумерных массивов часто используются два цикла for, чтобы заполнить элементы данными слева направо и сверху вниз. Напишем такой код:
int[][] twoD = new int[3][4]; // объявили двухмерный массив
int i, j, k = 0;
for (i = 0; i < 3; i++)
for (j = 0; j < 4; j++) {
twoD[i][j] = k;
k++;
}
for (i = 0; i < 3; i++) {
for (j = 0; j < 4; j++)
mInfoTextView.append(twoD[i][j] + " ");
mInfoTextView.append("\n");
}
В данном примере мы сначала заполнили двумерый массив данными, а затем снова прошлись по этому массиву для считывания данных.
Логическое представление данного двухмерного массива будет выглядеть следующим образом:
[0, 0] | [0, 1] | [0, 2] | [0, 3] |
[1, 0] | [1, 1] | [1, 2] | [1, 3] |
[2, 0] | [2, 1] | [2, 2] | [2, 3] |
Первое число в скобках обозначают ряд (строку), а второе число - столбец. Принято считать, что в массиве new int[M][N] первый размер означает количество строк, а второй - количество столбцов.
На экране после запуска примера мы увидим следующее:
0 1 2 3
4 5 6 7
8 9 10 11
При резервировании памяти под многомерный массив необходимо указать память только для первого измерения. Для остальных измерений память можно выделить отдельно.
int[][] twoD = new int[3][]; // память под первое измерение
// далее резервируем память под второе измерение
twoD[0] = new int[4];
twoD[1] = new int[4];
twoD[2] = new int[4];
В данном примере особого смысла в этом нет.
Еще одна интересная особенность при создании массива связана с запятой. Посмотрите на пример.
int[][] a = {{1, 2, 3}, {4, 0, 0,},};
System.out.println(Arrays.deepToString(a));
Вроде в конце используется лишняя запятая, но её наличие не приведёт к ошибке (только одна запятая). Это бывает удобно, когда надо скопировать или вставить кусок массива в коде. Кстати, метод deepToString() класса Arrays очень удобен для вывода двухмерных массивов.
Чтобы совсем сбить вас с толку, приведу ещё один правильный пример.
Integer[] Integer[] = {{1, 2, 3}, {4, 0, 0,},};
System.out.println(Arrays.deepToString(Integer));
Я уже упоминал, что квадратные скобки можно использовать двумя способами. Сначала мы поставили скобки у типа переменной, а потом у имени переменной. При этом мы использовали в качестве имени имя класса Integer. Однако, Java догадывается, что на этот раз используется не класс, а имя и разрешает такой синтаксис. Но лучше так не выпендриваться.
Размер имеет значение
Размер двумерного массива измеряется интересным способом. Длина массива определяется по его первой размерности, то есть вычисляется количество рядов.
int[][] matrix = new int[4][5];
System.out.println(matrix.length);
А если мы хотим узнать количество столбцов в ряду? Тогда указываете ряд, а затем вычисляете у него количество столбцов.
// число колонок у третьего ряда
System.out.println(matrix[2].length);
Не забывайте, что в массивах ряды могут содержать разное количество столбцов.
Класс Arrays
Класс java.util.Arrays предназначен для работы с массивами. Он содержит удобные методы для работы с целыми массивами:
- copyOf() − предназначен для копирования массива
- copyOfRange() − копирует часть массива
- toString() − позволяет получить все элементы в виде одной строки
- sort() — сортирует массив методом quick sort
- binarySearch() − ищет элемент методом бинарного поиска
- fill() − заполняет массив переданным значением (удобно использовать, если нам необходимо значение по умолчанию для массива)
- equals() − проверяет на идентичность массивы
- deepEquals() − проверяет на идентичность массивы массивов
- asList() − возвращает массив как коллекцию
Подготовка изображений для игры Змейка
Прежде всего, подготовим необходимые изображения, которые понадобятся при создании игры. На этапе разработки можно взять простые изображения, сделанные в любом графическом редакторе и писать программный код с их использованием. Вполне подойдут картинки, найденные в интернете или сделанные самостоятельно. Когда игра будет закончена, можно сделать более внушительный дизайн, заменив исходные варианты картинками такого же размера, но с более привлекательным дизайном. Вспомним, что основной формат при разработке на Java –это формат PNG. Именно в этом формате необходимо подготовить изображения.
Выполнить конвертацию в формат PNG можно во многих графических редакторах.
Для игры Змейка понадобятся пять изображений:
1) Основной фон
2) Объект для поедания Змейкой
3) Голова Змейки
4) Элемент тела Змейки
5) Изображение Конец Игры
Подготовим следующие изображения:
· fon.png (см. рис. 2) –это фоновое изображение, размер 800x650 –размеры окна по условию задания.
Рис. 2
· telo.png (см. рис. 3) –элемент тела Змейки, размер 20x20– размер одной клетки игрового поля по условию задания.
Рис. 3
· golova.png (см. рис. 4) –голова Змейки, размер 20x20 –размер одной клетки игрового поля по условию задания.
Рис. 4
· ob.png (см. рис. 5) –объект для поедания Змейкой, размер 20x20 –размер одной клетки игрового поля по условию задания.
Рис. 5
· endg.png (см. рис. 6) –изображение "Конец Игры", размер 200x100–размер взят произвольно, здесь главное, чтобы рисунок помещался на игровом поле.
Рис. 6
Все пять изображений поместим, например, в корень диска C:\. В процессе разработки игры изображения будут загружаться из корня диска C:\. После окончания создания игры мы поместим их внутрь JAR-архива.
Создание проекта и файлов классов игры Змейка
Откроемсреду разработки Eclipseдля Java и создадим новый проект Java. Для этого в меню выберем: File-New-Java Project (см. рис. 7)
Рис. 7
Укажем название проекта: zmeika (см. рис. 8) и нажмем кнопку Finish(Готово).
Рис. 8
В списке проектов добавится новый проект zmeika. Добавим к нему новый класс.Для этого нажмем на имя проекта левой клавишей мыши (выделим). Далее нажмем правую клавишу мыши, откроется дополнительное окно. Выберем New-Class(см. рис. 9):
Рис. 9
Это будет главный класс нашего проекта,в нем будет находиться метод main(). Укажем название класса: zmeika и поставим галочку public static void main(см.рис. 10):
Рис. 10
Далее нажимаем кнопкуFinish (Готово). В результате появится программный код нового класса, содержащий метод main() (см. рис. 11):
Рис. 11
При разработке игрыЗмейка мы не будем использовать визуальный конструктор, потому что интерфейс довольно простой. Элементы интерфейса - кнопки и надпись мы создадим программно. На первом занятии мы выяснили, что программирование игры Змейкаможно свести к программированию двумерного массива. Таймер отрисовки будет отображать двумерный массив, перенося его значения на игровое поле. Все объекты игрового поля будут представлены в массиве в виде чисел. Создание игры можно разбить на две основные части –это различные действия с массивом для перемещения змейки и графическое отображение игрового поля.
Для операций с массивом создадим еще один класс. Добавим к проекту еще один класс с названием: game (см.рис. 12), галочку public static void main() на этот раз ставить не нужно! (см. рис.12).
Рис. 12
В результате в нашемпроекте будет два файла (см.рис. 13, 14):
Рис. 13
Рис. 14
В файле game.javaбудет реализована вся логика игры –это операции с двумерным массивом. В файле zmeika.javaбудет реализована вся графика, построение интерфейса, обработка событий, отрисовка и настройка таймеров.
Начнем с класса game. Для первого уровня сложности достаточно выводить по центру только голову змейки, которая не перемещается и объект для поедания,появляющийся в случайном месте.
Сначала добавим свойства класса, которые нам понадобятся при работе с массивом. Нам будет достаточно только двумерного массива. Итак, начнем писать программный код в файле game.java:
public class game
{
// Двумерный массив для хранения игрового поля
public int[][] mas;
}
Объявление int[][] mas; означает двумерный массив целых чисел. Свойство класса –это переменная класса. Данную переменную класса мы сделали public –открытой. Это необходимо для доступности массива из другого класса. К данным массива мы будем обращаться для отрисовки данных игрового поля. Добавим конструктор класса:
public class game
{
// Двухмерный массив для хранения игрового поля
public int[][] mas;
// Конструкторкласса
public game()
{
//Создаем новый массив 30x30
mas = new int[30][30];
}
}
Конструктор класса автоматически вызывается при создании объекта на основании класса. Имя конструктора должно совпадать с именем класса.
В конструкторе мы создаем двумерный массив размером 30x30,тридцать строк и тридцать элементов в каждой строке. Именно такие размеры имеет игровое поле для змейки. Когда происходит объявление массива, массива еще нет. Он создается при помощи команды new. При объявлении массива мы лишь сообщаем, что тип данных–двумерный массив.
Далее нам понадобится метод для генерации положения объекта для поедания змейкой. Внутри (под конструктором класса) класса, добавим метод make_new():
// Генерация нового объекта в случайном месте
private void make_new()
{
//Глухой (бесконечныйцикл)
while(true)
{
// Получаем случайные значения x,y от 0 до 29
int x = (int)(Math.random()*30);
int y = (int)(Math.random()*30);
// Если в этом месте массива нулевое значение
// то помещаем туда объект для поедания змейкой
// и прерываем цикл
if (mas[y][x]==0)
{
mas[y][x] = -1;
// Прерываем цикл
break;
}
}
}
При рассмотрении алгоритма написания игры мы говорили, что свободные клетки игрового поля в массиве будут иметь нулевое значение, объект для поедания будет обозначен минус единицей:-1, голова змейки обозначена единицей: 1, а туловище змейки и -числа от двух и выше.
Это значит, что для размещения "объекта поедания" нужно найти случайно выбранную свободную ячейку.Алгоритм поиска заключается в следующем:мы ищем случайным образом ячейку до тех пор, пока не найдем свободную. Для такого поиска можно использовать бесконечный цикл:
//Глухой (бесконечный цикл)
while(true)
{
}
Цикл будет прерван в тот момент, когда будет найдена ячейка с нулевым значением:
// Если в этом месте массива нулевое значение
// то помещаем туда объект для поедания змейкой
// и прерываем цикл
if (mas[y][x]==0)
{
mas[y][x] = -1;
// Прерываем цикл
break;
}
Перед выходом из цикла записываем в эту ячейку минус единицу -"объект для поедания". Для поиска случайной ячейки на игровом поле используем следующую конструкцию:
// Получаем случайные значения x,y от 0 до 29
int x = (int)(Math.random()*30);
int y = (int)(Math.random()*30);
Для получения искомой ячейки нужно выбрать случайную строку и случайный номер элемента в строке. И эти значения (номер строки и номер элемента в строке) должны лежать от 0 до 29включительно. Нумерация в массиве начинается с нуля. Последний метод, который нам понадобится в этом классе – это метод для старта(запуска) игры. Под методом make_new()добавим методstart():
// Запуск игры (Старт)
public void start()
{
//Заполняем весь массив нулями
for (int i = 0; i < 30; i++) {
for (int j = 0; j < 30; j++) {
mas[i][j] = 0;
}
}
//Размещаем голову змейки по центру поля
mas[15][15] = 1;
//Формируем первый объект для поедания змейкой
make_new();
}
Этот метод содержит действия при начале игры. Сначала обнуляем весь массив при помощи двух вложенных циклов –это равноценно полному очищению игрового поля.Далее по центру игрового поля размещаем голову змейки (помещаем единицу):
//Размещаем голову змейки по центру поля
mas[15][15] = 1;
Теперь генерируем случайным образом "объект для поедания",вызывая метод make_new(), созданный на предыдущем шаге.Полностью программный код класса game для первого уровня сложности выглядит так:
public class game
{
// Двухмерный массив для хранения игрового поля
public int[][] mas;
// Конструкторкласса
public game()
{
//Создаем новый массив 30x30
mas = new int[30][30];
}
// Генерация нового объекта в случайном месте
private void make_new()
{
//Глухой (бесконечныйцикл)
while(true)
{
// Получаем случайные значения x,y от 0 до 29
int x = (int)(Math.random()*30);
int y = (int)(Math.random()*30);
// Если в этом месте массива нулевое значение
// то помещаем туда объект для поедания змейкой
// и прерываем цикл
if (mas[y][x]==0)
{
mas[y][x] = -1;
break;
}
}
}
// Запуск игры (Старт)
public void start()
{
//Заполняем весь массив нулями
for (int i = 0; i < 30; i++) {
for (int j = 0; j < 30; j++) {
mas[i][j] = 0;
}
}
//Размещаем голову змейки по центру поля
mas[15][15] = 1;
//Формируем первый объект для поедания змейкой
make_new();
}
}
Перейдем в другой файл нашего проекта: zmeika.java.В этом файле будет реализована остальная часть игры. В самом верху добавим необходимые библиотеки:
// Для обработки событий
import java.awt.event.*;
// Для работы с окнами
import javax.swing.*;
// Для работы с графикой
import java.awt.*;
// Для работы с изображениями
import javax.imageio.*;
// Для работы с файлами
import java.io.*;
Все эти библиотеки нам уже знакомы по игре "Новогодний дождь".Внутри метода main(), который является точкой входа в программу, добавим создание объекта "окно"с игровым полем:
// Главный класс программы
public class zmeika
{
// Методзапускаприложения
public static void main(String[] args)
{
// Создание объекта окна игрового поля
myFrame okno = new myFrame();
}
}
Сам класс myFrame будет создан на следующем шаге и будет располагаться под классом zmeika:
// Класс окна игрового поля
class myFrame extends JFrame
{
// Конструктор класса
public myFrame()
{
//Создание объекта панели и подключения ее к окну
myPanel pan = new myPanel();
Container cont = getContentPane();
cont.add(pan);
//Заголовококна
setTitle("Игра \"Змейка\"");
//Границы окна: расположение и размеры
setBounds(0, 0, 800, 650);
//Операция при закрытии окна - завершение приложения
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Запрет изменения размеров окна
setResizable(false);
//Отображение (показ) окна
setVisible(true);
}
}
Класс myFrameнаследуется от класса JFrame –класса окон. Внутри класса myFrameнаходится конструктор класса, который задаёт все характеристики окна. Все эти действия мы выполняли при создании игры "Новогодний дождь". Отдельного внимания заслуживает строка:
// Запрет изменения размеров окна
setResizable(false);
Она запрещает пользователю изменять размеры окна по ширине и высоте.
При задании заголовка окна слово "Змейка" находится внутри двойных кавычек, поэтому перед кавычками стоит наклонная черта \.:
//Заголовок окна
setTitle("Игра \"Змейка\"");
Следующие строки подключают панель к окну:
// Создание объекта панели и подключения ее к окну
myPanel pan = new myPanel();
Container cont = getContentPane();
cont.add(pan);
Класс myPanelбудет располагаться под классом myFrame. Этот класс реализует игровое поле и будет самым большим по объему программного кода.Создадим класс myPanelи добавим свойства (переменные)класса:
// Класс панели игрового поля
class myPanel extends JPanel
{
// Переменная для реализации логики игры
private game myGame;
// Таймеротрисовки
private Timer tmDraw;
// Изображения, используемыевигре
private Image fon,telo,golova,ob,endg;
// Надпись для количества очков
private JLabel lb;
// Двекнопки
private JButton btn1,btn2;
}
Среди свойств представлено все, что понадобится нам на игровом поле:
· переменная типа game(класс, созданный в самом начале для реализации двумерного массива),
· таймер для отрисовки,
· пять изображений для игры,
· текстовая надпись,
· две кнопки.
Добавим конструктор класса myPanel:
// Конструктор класса
public myPanel()
{
//Попытка загрузки всех изображений для игры
try
{
fon = ImageIO.read(new File("c:\\fon.png"));
telo = ImageIO.read(new File("c:\\telo.png"));
golova = ImageIO.read(new File("c:\\golova.png"));
ob = ImageIO.read(new File("c:\\ob.png"));
endg = ImageIO.read(new File("c:\\endg.png"));
}
catch (Exception ex) {}
//Создаем объект новой игры
myGame = new game();
//Запускаемигру
myGame.start();
//Создаем, настраиваем и запускаем таймер
// для отрисовки игрового поля
tmDraw = new Timer(20,new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
// Вызываемперерисовку -paintComponent()
repaint();
}
});
tmDraw.start();
setLayout(null);
lb = new JLabel("Счет: 0");
lb.setForeground(Color.WHITE);
lb.setFont(new Font("serif",0,30));
lb.setBounds(630, 200, 150, 50);
add(lb);
btn1 = new JButton();
btn1.setText("Новаяигра");
btn1.setForeground(Color.BLUE);
btn1.setFont(new Font("serif",0,20));
btn1.setBounds(630, 30, 150, 50);
btn1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
myGame.start();
}
});
add(btn1);
btn2 = new JButton();
btn2.setText("Выход");
btn2.setForeground(Color.RED);
btn2.setFont(new Font("serif",0,20));
btn2.setBounds(630, 100, 150, 50);
btn2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
System.exit(0);
}
});
add(btn2);
}
Рассмотрим представленный выше программный код подробно.
Вначале производим загрузку всех пяти изображений:
//Попытка загрузки всех изображений для игры
try
{
fon = ImageIO.read(new File("c:\\fon.png"));
telo = ImageIO.read(new File("c:\\telo.png"));
golova = ImageIO.read(new File("c:\\golova.png"));
ob = ImageIO.read(new File("c:\\ob.png"));
endg = ImageIO.read(new File("c:\\endg.png"));
}
catch (Exception ex) {}
Затем создаем объект на основании класса game и производим запуск игры:
//Создаем объект новой игры
myGame = new game();
myGame.start();
В этот