Дополнительное задание #2. Последовательный интерфейс доски Боггл

На этой неделе вы начнете разработку пользовательского интерфейса игры Боггл. Сосредоточимся на двух классах; один это "кнопка Боггл" которая отображает одну букву на доске Боггл, и другой класс "доска Боггл" который управляет отображением всей доски.

Чтобы облегчить себе жизнь, создайте свои классы пользовательского интерфейса на основе имеющихся классов Swing, просто расширьте их возможности там где это необходимо. Ваш класс Боггл-копка должен наследоваться от javax.swing.JButton, а класс Боггл-доска, содержащий коллекцию кнопок Боггл, должен наследоваться от javax.swing.JPanel.

И не забудьте как обычно добавить комментарии Javadoc к всему коду который вы напишите,

Вспоминаем пользовательский интерфейс Swing

Если вы забыли как добавляются обработчики событий для компонентов пользовательского интерфейсаSwing, то вот некоторые детали:

Боггл-кнопки

Ваш класс отображения Боггл-копки должен прорисовывать одну клетку на доске Боггл. В этом нет ничего концептуально сложного. Но мы хотим сделать для пользователя красивые подсказки, которые облегчают чтение игрового поля и отображают список слов из которых можно делать выбор. Но об этом после.

Назовите свой класс "кнопки Боггл" использую те же соглашения имен, которые приняты для именования компонентов Swing. Имена этих компонентов начинаются с буквы "J". Например, этот класс можно назвать "JBoggleButton."

Состояние кнопки Боггл должно хранить три вещи:

  1. Позиция кнопки на игровом поле Боггл. С этим можно поспорить, но некоторые свойства поля Боггл описанные ниже, гораздо легче реализовать, если кнопки знают свое место на доске.

    Позицию можно указать парой значений (x, y), конечно считая от нуля. Пусть позиция кнопки указывается в конструкторе, и кроме этого добавьте аксессоры.

    Не называйте аксессоры getX() и getY()!!! У компонентов Swing уже есть аксессоры с этими именами. Они используются для позиционирования компонентов пользовательского интерфейса в контейнере Swing. Совпадающие имена перепутают расположение компонентов вашего пользовательского интерфейса. (Я потратил несколько часов в поисках этого бага, не повторяйте той же ошибки!) Назовите аксессоры как нибудь иначе, например getBoardX() и getBoardY().

  2. Значение кнопки Боггл типа String. Можете воспользоваться готовыми методами getText() и setText(String) класса JButton, или сделать собственное поле и пару аксессор/мутатор. Опишите ваше решение в комментариях Javadoc вашего класса.
  3. Текущее состояние кнопки Боггл. Это состояние должно принимать одно из следующих значений:

    Для определения этих состояний воспользуйтесь перечисляемым типом (enum) Java (назовите его, например, "State"). Добавьте к вашему классу кнопки переменную этого типа с модификатором public. Теперь код внутри класса может использовать эти состояния, и код использующий этот ваш класс тоже имеет доступ к информации о состоянии кнопки.

    Сделайте аксессор и мутатор для состояния кнопки. Мутатор дополнительно должен прорисовывать внешний вид кнопки, в соответствии с ее текущим состоянием. (Детали приведены ниже.)

Мы хотим, чтобы пользовательский интерфейс был хорошо читаемым, и мы не хотим использовать для надписей шрифт "по умолчанию". Поэтому в конструкторе вашего класса, установите для кнопки большой легко читаемый шрифт. (Например шрифт sans-serif размером в 40-пунктов, ну или может быть вам больше нравятся шрифты serif.)

Рамки кнопки Боггл

Кнопки Боггл должны отображать свое текущее состояние (недоступна, доступна или выбрана) с помощью двух визуальных эффектов: "активного" состояния, и цвета рамки. Изменить "активное" состояние компонента Swing легко, но JButton по умолчанию не имеет рамки, поэтому ее нужно добавить с помощью метода setBorder(Border).

Добавьте к своему классу кнопки три константы: UNAVAILABLE_BORDER, AVAILABLE_BORDER, и SELECTED_BORDER. (Эти константы должны иметь модификатор доступа private, потому, что они нужны только внутри класса. Объявите их как private static final.) Проинициализируйте каждую константу вызовом подходящего метода javax.swing.BorderFactory, чтобы создать сплошную рамку шириной три пикселя.

После того как вы сделаете таким образом все три рамки, можно дописать ваш "изменяющий состояние" мутатор так, чтобы он менял внешний вид кнопки, следующим образом:

Как было указано выше, внешний вид кнопки надо менять в "изменяющем состояние" мутаторе. Дополнительно вызовите этот мутатор из конструктора; Не меняйте эти значения нигде кроме как внутри мутатора.

Отображение досок Боггл

Когда ваш класс кнопки Боггл будет готов , можно перейти к классу "Доска Боггл". Этот класс должен прорисовывать доску размером N×N составленную из кнопок Boggle, позволять пользователям создавать слова из букв на игровом поле Боггл. Следуя правилам именования компонентов пользовательского интерфейса Swing, вам следует назвать этот класс "JBoggleBoard". Конструктор класса имеет единственный аргумент N, задающий размерность отображаемой доски.

Класс JBoggleBoard конечно должен иметь ссылку на экземпляр класса BoggleBoard, и кнопки которые отображают содержимое объекта BoggleBoard.

Отображение доски это не столь сложная задача, так как у вас уже есть класс кнопки Боггл. Можно сделать такой метод:

    public void setBoard(BoggleBoard b)

Метод просто в цикле перебирает все кнопки, устанавливая состояние каждой, так чтобы оно соответствовало значению клетки взятому из BoggleBoard. (Можно вызывать исключение IllegalArgumentException если размер BoggleBoard не совпадает с размером JBoggleBoard.)

Построение слов

Хотя этот класс может просто давать игроку возможность нажать любую уже использованную кнопку, нам хочется добавить к этому классу больше функций. По мере того как игрок формирует слово, мы хотим показывать игроку какие буквы уже являются частью этого слова (потому что каждая клетка доски может использоваться в слове только один раз), а также какие буквы еще доступны для выбора. Итак будем контролировать выбор следующим образом:

Заведем список (т.е. ArrayList) "выбранных кнопок". Первоначально список пуст, и кнопки добавляются к нему по мере того как игрок составляет свое слово.

Есть несколько способов обновлять изображение доски, но легче всего создать отдельный private метод который выполняет задачу обновления состояний кнопок. Он должен обрабатывать два случая:

  1. Если выбранные кнопки отсутствуют, перебрать все кнопки и изменить их состояние на "доступны."
  2. Иначе выполнить эти шаги:
    1. Перебрать все кнопки и установить их в состояние "недоступны."
    2. Перебрать все элементы списка выбранных кнопок, и установить каждую кнопку из списка в состояние "выбрана."
    3. Извлечь последнюю кнопку из списка выбранных, и установить всех ее соседей в состояние "доступны," если их нет в списке "выбранных кнопок". (Подсказка: Возможность получения позиции кнопки на доске может быть очень полезна на этом шаге ...)

Есть еще одна ситуация которую должен обрабатывать класс отображающий доску. Если пользователь нажимает на кнопку, которая уже выбрана. В этом случае, нужно сократить список выбранных кнопок до этой кнопки, и затем соответственно обновить состояния кнопок. Это свойство программы позволит игроку отменять свои ходы и продолжать игру с позиции до которой сделана отмена.

Методы

Вот список методов которые должны быть реализованы в вашем классе JBoggleButton:

Тестирование кода

Так как тестировать классы пользовательского интерфейса как правило очень сложно, вам нужно всего лишь добавить простой метод main() к классу JBoggleBoard. Он должен вывести доску на экран, для того чтобы убедиться, что она работает. Он должен выглядеть примерно так:

    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
              JFrame f = new JFrame("BoggleTest");
              f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

              JBoggleBoard boardGUI = new JBoggleBoard(BoggleBoard.DEFAULT_SIZE);
              f.add(boardGUI);

              f.pack();
              f.setVisible(true);
              f.setSize(300, 300);

              boardGUI.setBoard(new BoggleBoard());
            }
        });
    }

После того как вы добавили подобный код к классу JBoggleBoard, его можно запустить в командной строке, вот так:

    java JBoggleBoard

Если все сделано правильно, вы увидите свой пользовательский интерфейс, и сможете составлять слова на доске Боггл.

Если вы желаете улучшить свою программу, вот некоторые идеи:


Copyright (C) 2015, California Institute of Technology. All rights reserved.