Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Pyatnashki.docx
Скачиваний:
1
Добавлен:
01.05.2025
Размер:
677.9 Кб
Скачать

2.2. Описание основных классов.

В программе используется единственный нестандартный класс App, который представляет собой реализацию коробки с костяшками, содержит игровую логику и управляет отображением графики на экране. Класс App наследуется от стандартного класса JFrame, что даёт ему функциональность окна (в понимании операционной системы Windows или оконных менеджеров других ОС).

Переменная _grid — двумерный массив чисел, который является абстракцией игрового поля (набора костяшек с числами), а двумерный массив кнопок (экземпляров класса JButton) _btns выполняет роль визуализатора этой абстракции.

В игре также используется класс Timer для подсчёта времени, которое было затрачено на решение головоломки.

// Двумерный массив, хранящий номера фишек на игровом поле.

private int _grid[][];

// Двумерный массив кнопок, представляющих фишки на игровом поле.

private JButton _btns[][];

// Размер игрового поля.

private final int _gridSize = 4;

// Статическая переменная, хранящая экземпляр текущего приложения.

private static App _app;

// Хранит информацию о том, не завершена ли ещё игра.

private boolean _gameOver;

// Таймер для подсчёта времени.

private javax.swing.Timer _timer;

// Количество затраченных на игру секунд.

private int _time;

// Заголовок окна.

final String _title = "Пятнашки";

Класс App содержит следующие методы:

tryMove — пытается совершить перемещение костяшки (вызывается при нажатии соответствующей кнопки-костяшки) и в случае удачного перемещения, обновляет вид игрового поля, а также проверяет, не завершена ли после данного действия игра. /*

* Пытается совершить перемещение фишки.

*/

private void tryMove(JButton btn) {

int value = Integer.parseInt(btn.getText());

int i = 0, j = 0;

// Поиск координат пустой клетки.

search: {

for (; j < _gridSize; ++j)

for (i = 0; i < _gridSize; ++i)

if (_grid[j][i] == value)

break search;

}

// Было ли совершено перемещение.

boolean moved = false;

// Пытаемся переместить фишку в четырёх направлениях.

if (i > 0 && _grid[j][i - 1] == 0)

{

// Влево...

_grid[j][i - 1] = value;

moved = true;

}

else if (i < _gridSize - 1 && _grid[j][i + 1] == 0)

{

// Вправо...

_grid[j][i + 1] = value;

moved = true;

}

else if (j > 0 && _grid[j - 1][i] == 0)

{

// Вверх...

_grid[j - 1][i] = value;

moved = true;

}

else if (j < _gridSize - 1 && _grid[j + 1][i] == 0)

{

// Вниз...

_grid[j + 1][i] = value;

moved = true;

}

// Если удалось совершить перемещение, обновляем игровое поле.

if (moved)

{

_grid[j][i] = 0;

updateGrid();

// Если это было первое перемещение за текущую игру,

// запускаем таймер.

if (!_gameOver && !_timer.isRunning()) {

_time = 0;

_timer.start();

}

}

}

shuffle — перемешивает костяшки на игровом поле. Вызывается перед началом новой игры. /*

* Перемешивает цифры на игровом поле.

*/

private void shuffle() {

// Сначала расставляем фишки в порядке возрастания.

for (int j = 0; j < _gridSize; ++j)

for (int i = 0; i < _gridSize; ++i)

_grid[j][i] = i + j * 4 + 1;

_grid[_gridSize - 1][_gridSize - 1] = 0;

// Генератор случайных чисел.

Random rnd = new Random();

// Начальные координаты пустой клетки.

int x = _gridSize - 1;

int y = _gridSize - 1;

// Перемешиваем...

for (int k = 0; k < 100; ++k)

{

// Выбираем случайное направление, откуда будет перемещена

// фишка в пустую клетку.

int dir = rnd.nextInt(4);

// Пытаемся переместить...

switch(dir)

{

case 0:

if (x > 0)

{

_grid[y][x] = _grid[y][x-1];

_grid[y][x - 1] = 0;

--x;

}

else

--k;

break;

case 1:

if (y > 0)

{

_grid[y][x] = _grid[y-][x];

_grid[y - 1][x] = 0;

--y;

}

else

--k;

break;

case 2:

if (x < _gridSize - 1)

{

_grid[y][x] = _grid[y][x+1];

_grid[y][x + 1] = 0;

++x;

}

else

--k;

break;

case 3:

if (y < _gridSize - 1)

{

_grid[y][x] = _grid[y+][x];

_grid[y + 1][x] = 0;

++y;

}

else

--k;

break;

}

}

// Если вдруг оказалось, что фишки всё ещё стоят упорядоченно

// (что крайне маловероятно), перемешиваем их ещё раз.

if (testGrid())

shuffle();

// Обновляем игровое поле.

updateGrid();

_gameOver = false;

}

testGrid — проверяет, не завершена ли игра (игра считается завершённой, когда все костяшки расположены в порядке возрастания, а пустая клетка находится в конце после пятнадцатой костяшки). /*

* Проверяет, не завершена ли игра.

*/

private boolean testGrid() {

// Проверяем чтобы фишки располагались на поле в порядке

// ворзрастания номеров. Если нашли несоответствие этому правилу,

// то возвращаем false.

for (int j = 0; j < _gridSize; ++j)

for (int i = 0; i < _gridSize; ++i)

if (_grid[j][i] != i + j * 4 + 1 && _grid[j][i] != 0)

return false;

// Если всё хорошо, отключаем счётчик времени и завершаем игру.

_timer.stop();

_gameOver = true;

return true;

}

updateGrid —обновляет состояние игрового поля (массива кнопок) в соответствии с его абстракцией (массивом _grid). /*

* Обновляет кнопки по информации из двумерного массива.

*/

private void updateGrid() {

// Всем кнопкам задаём номера в соответствии с массивом _grid.

for (int j = 0; j < _gridSize; ++j)

for (int i = 0; i < 4; ++i)

{

int value = _grid[j][i];

JButton btn = _btns[j][i];

btn.setText(Integer.toString(value));

btn.setVisible(value != 0);

}

}

createMenu —метод утилитарного характера, предназначен для создания меню в программе, вызывается в конструкторе класса App. /*

* Создаёт меню.

*/

private void createMenu() {

// Полоска меню.

JMenuBar menu = new JMenuBar();

setJMenuBar(menu);

// Кнопка "Игра".

JMenu mnuGame = new JMenu("Игра");

menu.add(mnuGame);

// Кнопка "Новая игра"...

JMenuItem mnuNewGame = new JMenuItem("Новая игра");

mnuGame.add(mnuNewGame);

// ...при нажатии на неё, нужно перемешать игровое поле.

mnuNewGame.addActionListener(new ActionListener() {

public void actionPerformed(ActionEvent e) {

setTitle(_title);

_app.shuffle();

}

});

// Кнопка "Выход"...

JMenuItem mnuExit = new JMenuItem("Выход");

mnuGame.add(mnuExit);

// ...при нажатии на неё, завершаем приложение.

mnuExit.addActionListener(new ActionListener() {

public void actionPerformed(ActionEvent e) {

_app = null;

System.exit(0);

}

});

}

Конструктор основного класса приложения:

public App() {

// Начальные настройки окна.

setTitle(_title);

_app = this;

createMenu();

setLayout(new GridLayout(4, 4, 5, 5));

setSize(400, 400);

setLocationRelativeTo(null);

setResizable(false);

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

setVisible(true);

// Создаём массивы для хранения фишек.

_grid = new int[_gridSize][_gridSize];

_btns = new JButton[_gridSize][_gridSize];

// Создаём кнопки.

for (int j = 0; j < _gridSize; ++j) {

_btns[j] = new JButton[_gridSize];

for (int i = 0; i < 4; ++i)

{

JButton btn = new JButton();

_btns[j][i] = btn;

add(btn);

// Обработчик нажатия на кнопку.

btn.addActionListener(new ActionListener() {

@Override

public void actionPerformed(ActionEvent e) {

if (!_gameOver)

{

tryMove((JButton)e.getSource());

if (testGrid())

JOptionPane.showMessageDialog(

_app,

"Вы правильно собрали головоломку!\nЗатрачено времени: " +

Integer.toString(_time) + " секунд.",

"Победа!",

JOptionPane.INFORMATION_MESSAGE);

}

}

});

}

}

// Создаём таймер для подсчёта времени.

_timer = new javax.swing.Timer(

1000,

new ActionListener() {

@Override

public void actionPerformed(ActionEvent e) {

++_time;

setTitle(_title + " (время: " +

Integer.toString(_time) + " секунд)");

}

});

// Перемешиваем фишки на поле.

shuffle();

}

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]