Разработка игрового приложения "Домино"

Размещение элементов графического интерфейса, обработка событий в нем. Написание программы "Домино", результатом работы которой будет графический интерфейс, реализующий одноименную настольную игру. Объектная декомпозиция классов. Текст программы.

Рубрика Программирование, компьютеры и кибернетика
Вид курсовая работа
Язык русский
Дата добавления 13.10.2014
Размер файла 404,3 K

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.

Размещено на http://www.allbest.ru

Размещено на http://www.allbest.ru

Государственное образовательное учреждение высшего

Профессионального образования

«Санкт-Петербургский государственный

Политехнический университет»

Инженерно-экономический институт

Кафедра «Информационные системы в экономике и менеджменте»

КУРСОВОЙ ПРОЕКТ

По дисциплине «Объектно-ориентированный анализ и программирование»

На тему: Разработка игрового приложения «Домино»

Выполнил: студент гр. 1074/2

Громова М.В.

Принял:доцент

Чанцев В.П.

Санкт-Петербург

2013

Содержание

Введение

1. Графический интерфейс в Java

1.1 Элементы графического интерфейса

1.2 Размещение элементов графического интерфейса

1.3 Обработка событий в графическом интерфейсе

2. Решение практической задачи «Домино»

2.1 Постановка задачи

2.2 Объектная декомпозиция классов

Заключение

Список литературы

Приложение 1. Текст программы

Приложение 2. Тестовый пример

Введение

Целью данного курсового проекта является написание программы «Домино», результатом работы которой будет графический интерфейс, реализующий одноименную настольную игру.

Для реализации поставленной цели необходимо решить следующие задачи:

Изучить особенности графических интерфейсов на языке Java;

Выяснить, как реализуется обработка событий на языке Java;

Написать код программы.

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

В соответствии с поставленными задачами работа имеет следующую структуру:

Особенности графических интерфейсов на языке Java (элементы графических интерфейсов, их размещение, обработка событий);

Описание кода программы.

Глава 1. Графический интерфейс в Java

1.1 Элементы графического интерфейса

В Java есть два основных пакета для создания графических интерфейсов (Graphics User Interface). Это Abstract Windows Toolkit (AWT) и Swing. Остановимся подробно на первом их них.

AWT - набор классов Java, каждый из которых отвечает за реализацию функций и отображение того или иного элемента графического интерфейса пользователя (GUI). Практически все классы визуальных компонентов являются потомками абстрактного класса Component. Лишь визуальные элементы меню наследуются от другого класса - MenuComponent. Управляющие элементы представлены следующими классами:

? Button (кнопка);

? Checkbox (кнопка с независимой фиксацией);

? Choice (раскрывающийся список Windows);

? Label (строка);

? List (список выбора Windows);

?Scrollbar (полоса прокрутки).

Это достаточно простые классы, наследуемые от абстрактного класса Component напрямую.

Однако в составе java.awt имеются классы интерфейсных элементов, имеющие промежуточного предка. Хорошим примером тому является класс Panel для создания различных панелей. У него имеется промежуточный абстрактный класс-предок Container, служащий родоначальником многих классов-контейнеров, способных содержать в себе другие элементы интерфейса. От этого же класса наследуется класс окна Window, представляющий на экране простейшее окно без меню и рамки. У этого класса есть два часто используемых потомка: Dialog, название которого говорит само за себя, и Frame - стандартное окно Windows. Еще один промежуточный класс TextComponent порождает два полезнейших в работе класса - TextField (аналог строки ввода Windows) и многострочное окно текстового ввода TextArea. Особняком от всех элементов стоит класс Canvas. Его визуальное представление - пустой квадрат, на котором можно выполнять рисование и который может обрабатывать события нажатия кнопок мыши.

От своего предка Component все визуальные элементы перенимают общее для них всех поведение, связанное с их визуальной и функциональной сторонами. Вот список основных, выполняемых компонентами, функций и методов для их реализации:

?изменение шрифта - методы getFont, setFont, getFontMetrics;

?изменение цвета шрифта - методы setForeground(Color) и getForeground() - для установки и чтения цвета самого шрифта, а также setBackground(Color) и getBackground() для установки, а также чтения цвета фона, на котором отображается текст;

?размер и позиция на экране - методы preferredSize() и minimumSize() сообщают менеджеру раскладок о предпочтительном и минимальном размерах компонента, соответственно;

?отображение компонента - методы paint(), update() и repaint();

?обработка сообщений - методы handleEvent(), action(), keyDown(), keyUp(), mouseDown(), mouseUp(), mouseDrag(), mouseMove(), mouseEnter() и mouseExit().

1.2 Размещение элементов графического интерфейса

Для того, чтобы управлять расположением элементов внутри окон-контейнеров, в Java существует менеджер раскладок (layout manager). От него наследуются пять классов, определяющих тот или иной тип расположения компонентов пользовательского интерфейса в окне. Когда требуется изменить тип расположения, создается тот или иной класс раскладки, отвечающий запросам пользователя, и он передается в вызываемый метод setLayout(), изменяющий текущую раскладку:

// Установить расположение элементов вдоль рамки окна

setLayout(new BorderLayout());

Дадим краткую характеристику классам-раскладкам.

FlowLayout. Это простейший способ расположения элементов один за другим, применяемый по умолчанию. Когда в одной строке уже не помещаются новые элементы, заполнение продолжается с новой строки.

CardLayout. При раскладке этого типа элементы размещаются один за другим, как карты в колоде. Обычно такой расклад удобен, если необходимо динамически изменять интерфейс окна. Кроме того, можно располагать элементы так, чтобы они были один над другим по очереди.

BorderLayout. Эта раскладка размещает элементы либо рядом с выбранным краем окна, либо в центре. Для этого после установки BorderLayout добавление элементов в окно-контейнер производится методом add() с дополнительным параметром, задаваемым строками North, South, East, West и Center. Каждая из них означает тот край окна, к которому необходимо прижать вставляемый элемент.

GridLayout располагает элементы один за другим внутри некоторой условной таблицы. Все элементы будут одинакового размера. Размер ячеек можно программно изменять.

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

1.3 Обработка событий в графическом интерфейсе

Событие (event) в библиотеке AWT возникает при воздействии на компонент какими-нибудь манипуляциями мышью, при вводе с клавиатуры, при перемещении окна, изменении его размеров.

Объект, в котором произошло событие, называется источником(source) события.

Все события в AWT классифицированы. При возникновении события исполняющая система Java автоматически создает объект соответствующего событию класса. Этот объект не производит никаких действий, он только хранит все сведения о событии.

Во главе иерархии классов-событий стоит класс Eventobject из пакета java.util -- непосредственное расширение класса object. Его расширяет абстрактный класс AWTEvent из пакета java.awt -- глава классов, описывающих события библиотеки AWT. Дальнейшая иерархия классов-событий показана на рис. 1.1. Все классы, отображенные на рисунке, кроме класса AWTEvent, собраны в пакет java.awt.event.

События типа ComponentEvent, FocusEvent, KeyEvent, MouseEvent возникают во всех компонентах.

А события типа ContainerEvent -- только в контейнерах: Container, Dialog, FileDialog, Frame, Panel, ScrollPane, Window.

Рис.1. Иерархия классов, описывающих события AWT

События типа WindowEvent возникают ТОЛЬКО в окнах: Frame, Dialog, FileDialog, Window.

События типа TextEvent генерируются только в контейнерах TextComponent, TextArea, TextField.

События типа ActionEvent проявляются только в контейнерах Button, List, TextField.

События типа ItemEvent возникают только в контейнерах Checkbox, Choice, List.

Наконец, события типа AdjustmentEvent возникают только в контейнере Scrollbar.

Узнать, в каком объекте произошло событие, можно методом getsource класса Eventobject. Этот метод возвращает тип object.

В каждом из этих классов-событий определен метод paramstring(), возвращающий содержимое объекта данного класса в виде строки string. Кроме того, в каждом классе есть свои методы, предоставляющие те или иные сведения о событии.

Методы обработки событий описаны в интерфейсах-слушателях (listener). Для каждого показанного на рис. 1.1 типа событий, кроме InputEvent (это событие редко используется самостоятельно), есть свой интерфейс. Имена интерфейсов составляются из имени события и слова Listener, например, ActionListener, MouseListener. Методы интерфейса "слушают", что происходит в потенциальном источнике события. При возникновении события эти методы автоматически выполняются, получая в качестве аргумента объект-событие и используя при обработке сведения о событии, содержащиеся в этом объекте.

Чтобы задать обработку события определенного типа, надо реализовать соответствующий интерфейс. Классы, реализующие такой интерфейс, классы-обработчики (handlers) события,, называются слушателями (listeners): они "слушают", что происходит в объекте, чтобы отследить возникновение события и обработать его.

Чтобы связаться с обработчиком события, классы-источники события должны получить ссылку на экземпляр EventHandler класса-обработчика события одним из методов addXxxListener(XxxEvent eventHandier), где Ххх -- имя события.

Такой способ регистрации, при котором слушатель оставляет "визитную карточку" источнику для своего вызова при наступлении события, называется обратный вызов (callback). Обратное действие -- отказ от обработчика, прекращение прослушивания -- выполняется методом removeXxxListener().

Таким образом, компонент-источник, в котором произошло событие, не занимается его обработкой. Он обращается к экземпляру класса-слушателя, умеющего обрабатывать события, делегирует (delegate) ему полномочия по обработке.

Такая схема получила название схемы делегирования (delegation). Она удобна тем, что можно легко сменить класс-обработчик и обработать событие по-другому или назначить несколько обработчиков одного и того же события. С другой стороны, можно один обработчик назначить на прослушивание нескольких объектов-источников событий.

Эта схема кажется слишком сложной, но ей часто пользуются в жизни. Допустим, кто-то решил оборудовать квартиру. Он помещает в нее, как в контейнер, разные компоненты: мебель, сантехнику, электронику, антиквариат. Предполагается, что может произойти неприятное событие -- квартиру посетят воры, -- и хозяин хочет его обработать. Известно, что классы-обработчики этого события -- охранные агентства, -- тогда следует обратиться к некоторому экземпляру такого класса. Компоненты-источники события, т. е. те, которые могут быть украдены, присоединяют к себе датчики методом addXxxListener(). Затем экземпляр-обработчик "слушает", что происходит в объектах, к которым он подключен. Он реагирует на наступление только одного события -- похищения прослушиваемого объекта, -- прочие события, например, короткое замыкание или обрыв водопроводной трубы, его не интересуют. При наступлении "своего" события он действует по контракту, записанному в методе обработки.

Глава 2. Решение практической задачи «Домино»

2.1 Постановка задачи

Составить программу, которая раздает игрокам кости для игры в домино и моделирует игру. В качестве объектов выступают кости домино. Методы - выставление кости в тот или иной конец уже существующей цепочки костей. Предусмотреть контроль ситуации "рыба".

2.2 Объектная декомпозиция классов

Рассмотрим представленную на Рисунке 2 диаграмму классов.

Для решения поставленной задачи потребуется создать класс костей - Bone, в котором будут заданы следующие поля:

Поля X и Y - координаты точки, задающие положение центра кости домино на экране.

Поля dirX и dirY - направление, в котором расположена кость домино на экране.

Поля points1 и points2 - очки на кости домино с левой и правой стороны.

В этом же классе описан метод show(), который осуществляет отображение кости домино на экране.

Кроме класса Bone в программе создан класс MainFrame, наследник класса Frame.

В классе MainFrame описан конструктор окна приложения, который вызывается в статическом методе main().

В методе main() вызываются конструктор для создания объектов-костей домино, которые заносятся в ArrayList<Bone>playerBones. В этом методе вызывается инициализатор слушателей(Listener) кнопок главного окна. При нажатии на кнопку «Начать» запускается отрисовка костей домино, которые были розданы игрокам. Первым ходит тот, у кого на руках кость {1, 1}. Далее игроки делают ходы, постепенно выстраивается цепь. Игра продолжается до тех пор, пока не наступит ситуация «Рыба» или пока один из игроков не избавится от всех фишек на своих руках.

Рис.2. Диаграмма классов

Заключение

В представленном курсовом проекте были рассмотрены основные понятия языка программирования Java, которые касаются графических интерфейсов, а именно: основные элементы графического интерфейса, их размещение, обработка событий.

На Java нами была написана программа, которая реализует настольную игру «Домино».

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

Список литературы

Васильев А.Н. Объектно-ориентированное программирование для магистров и бакалавров: базовый курс по объектно-ориентированному программированию. - Санкт-Петербург, Питер, 2011г - 396 с.

Брюс Эккель. Философия Java. - Санкт-Петербург,Питер,2009 г- 640 с.

Приложение 1. Текст программы

интерфейс игровое приложение домино

package domino;

import java.awt.*;

/ * класс, который задает кость как графически, так и логически

public class Bone {

static final byte width = 32;

static final byte height = width * 2;

static final byte pointSize = 6;

static final Color colorMarked = Color.RED;

static final Color colorBack = Color.WHITE;

static final Color colorPoint = Color.BLUE;

private byte points1, points2;

private int X, Y;

private byte dirX, dirY;

static byte[][][] pointCoords = {

{},

{{0, 0}},

{{-1, -1}, {+1, +1}},

{{-1, -1}, {0, 0}, {+1, +1}},

{{-1, -1}, {+1, -1}, {-1, +1}, {+1, +1}},

{{-1, -1}, {+1, -1}, {-1, +1}, {+1, +1}, {0, 0}},

{{-1, -1}, {+1, -1}, {-1, +1}, {+1, +1}, {0, -1}, {0, +1}}

};

private boolean isMarked;

Bone(byte p1, byte p2) {

points1 = p1;

points2 = p2;

isMarked = false;

}

int getX() {

return X;

}

int getY() {

return Y;

}

/**

* Получение размер по X

*/

int getSizeX() {

if (dirX != 0) {

return height;

} else {

return width;

}

}

Bone setColorMarked() {

isMarked = true;

return this;

}

Bone setColorUsual() {

isMarked = false;

return this;

}

/**

* Получение размер по Y

*/

int getSizeY() {

if (dirX != 0) {

return width;

} else {

return height;

}

}

/**

* Получение очков со стороны

*/

byte points(int side) {

if (side == 0) {

return points1;

}

if (side == 1) {

return points2;

}

return -1;

} /**

* Получить размерности кости на экране для опеределения области прикосновения

*/

int[] getBounds() {

int sx = getSizeX(), sy = getSizeY();

return new int[]{X - sx / 2, X + sx / 2, Y - sy / 2, Y + sy / 2};

}

/**

* Отобразить кость

*/

void show(Graphics G) {

int sx = getSizeX(), sy = getSizeY();

G.setColor(colorBack);

G.fillRect(X - sx / 2, Y - sy / 2, sx, sy);

if (isMarked) {

G.setColor(colorMarked);

} else {

G.setColor(colorPoint);

}

G.drawRect(X - sx / 2, Y - sy / 2, sx - 1, sy - 1);

G.setColor(colorPoint);

if (dirX != 0) {

G.drawLine(X, Y - sy / 2 + 3, X, Y + sy / 2 - 4);

} else {

G.drawLine(X - sx / 2 + 3, Y, X + sx / 2 - 4, Y);

}

int x1 = X - dirX * sx / 4, y1 = Y - dirY * sy / 4;

for (int s = 1; s <= 2; s++) {

int p = points1;

if (s == 2) p = points2;

for (int i = 0; i < p; i++) {

//int d=width*i/(p+1)-pointSize/2;

int dx = pointCoords[p][i][0] * width / 4;

int dy = pointCoords[p][i][1] * width / 4;

G.fillOval(x1 + dx - pointSize / 2, y1 + dy - pointSize / 2,

pointSize, pointSize);

}

x1 += dirX * sx / 2;

y1 += dirY * sy / 2;

}

}

/**

* Спрятать кость

*/

void hide(Graphics G, Color back) {

G.setColor(back);

int sx = getSizeX(), sy = getSizeY();

G.fillRect(X - sx / 2, Y - sy / 2, sx, sy);

}

/**

* Перемещение кости на доске

*/

void moveTo(int x, int y, Graphics G, Color back) {

hide(G, back);

this.X = x;

this.Y = y;

show(G);

}

/**

* Поворот кости на доске

*/

void rotate(int dirX, int dirY, Graphics G, Color back) {

assert dirX >= -1 && dirX <= +1 && dirY >= -1 && dirY <= +1;

hide(G, back);

this.dirX = (byte) dirX;

this.dirY = (byte) dirY;

show(G);

}

/**

* Плавное перемещение кости на доске

*/

void moveSliding(int x2, int y2, int time, Graphics G, Color back) {

int x1 = getX(), y1 = getY();

int dt = 1000 / 25;

int n = time / dt;

for (int p = 1; p <= n; p++) {

int xp = x1 + (x2 - x1) * p / n;

int yp = y1 + (y2 - y1) * p / n;

moveTo(xp, yp, G, back);

long t = System.currentTimeMillis();

do {

} while (System.currentTimeMillis() - t < dt);

}

}

}

package domino;

import javax.swing.*;

import java.awt.*;

import java.awt.event.*;

import java.util.ArrayList;

import java.util.Timer;

import java.util.TimerTask;

public class MainFrame extends Frame {

private Graphics graphics;

private Color backgroundColor;

private final static int PLAYERS_COUNT = 4;

private final static int MAX_BONES_COUNT = 7;

private final static int MAX_BONE_VALUE = 6;

private int currentPlayerIdx;

private int passesCount = 0;

private int[] placeJ = new int[2];

private int[] placeK = new int[2];

private int[] rotationJ = new int[2];

private int[] rotationK = new int[2];

private byte[] endPoints = new byte[2];

private ArrayList<Bone>[] playersBones = new ArrayList[PLAYERS_COUNT];

private ArrayList<Bone> bonesOnTheDesk;

private boolean selected;

private int selectedIdx;

private boolean gameStarted;

private boolean isHandling;

private boolean isChoosingBone;

private int selectedOnBoard;

public MainFrame() {

initComponents();

graphics = this.getGraphics();

backgroundColor = getBackground();

}

/**

* Строка, выводящая кто сейчас играет

*/

private String getCurrentPlayer() {

return "Текущий игрок: " + ("Человек №" + (currentPlayerIdx + 1));

}

/**

* Обновление заголовка

*/

private void updateAppTitle() {

setTitle("Домино. " + getCurrentPlayer());

}

/**

* Инициализация авт компонент

*/

private void initComponents() {

Button buttonStart = new Button();

Button buttonStop = new Button();

setBackground(new Color(102, 102, 0));

setCursor(new Cursor(Cursor.HAND_CURSOR));

setLocationRelativeTo(null);

setResizable(false);

updateAppTitle();

selected = false;

isHandling = false;

addWindowListener(new WindowAdapter() {

public void windowActivated(WindowEvent evt) {

formWindowActivated(evt);

}

public void windowClosing(WindowEvent evt) {

exitForm(evt);

}

public void windowOpened(WindowEvent evt) {

formWindowOpened(evt);

}

});

// перехватываем действия игрока

addMouseListener(new MouseListener() {

public void mouseClicked(MouseEvent e) {

}

public void mousePressed(MouseEvent e) {

}

public synchronized void mouseReleased(MouseEvent e) {

if (isChoosingBone) {

int x = e.getX();

int y = e.getY();

selectedOnBoard = selectOnBoard(x, y);

doMove();

} else if (!isHandling && gameStarted && !selected) {

isHandling = true;

int x = e.getX();

int y = e.getY();

selectedIdx = selectBone(x, y);

selected = (selectedIdx != -1);

doMove();

isHandling = false;

}

}

public void mouseEntered(MouseEvent e) {

}

public void mouseExited(MouseEvent e) {

}

});

addComponentListener(new ComponentAdapter() {

public void componentShown(ComponentEvent evt) {

formComponentShown(evt);

}

});

buttonStart.setLabel("Начать");

buttonStart.addActionListener(new ActionListener() {

public void actionPerformed(ActionEvent evt) {

gameStarted = true;

startButtonListener(evt);

}

});

buttonStop.setLabel("Стоп");

buttonStop.addActionListener(new ActionListener() {

public void actionPerformed(ActionEvent evt) {

gameStarted = false;

stopButtonListener(evt);

}

});

GroupLayout layout = new GroupLayout(this);

this.setLayout(layout);

layout.setHorizontalGroup( layout.createParallelGroup(GroupLayout.Alignment.LEADING)

.addGroup(layout.createSequentialGroup()

.addContainerGap()

.addComponent(buttonStart, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)

.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)

.addComponent(buttonStop, GroupLayout.PREFERRED_SIZE, 52, GroupLayout.PREFERRED_SIZE)

.addContainerGap(355, Short.MAX_VALUE))

); layout.setVerticalGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)

.addGroup(layout.createSequentialGroup().addContainerGap().addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)

.addComponent(buttonStop, GroupLayout.PREFERRED_SIZE, 37, GroupLayout.PREFERRED_SIZE)

.addComponent(buttonStart, GroupLayout.PREFERRED_SIZE, 37, GroupLayout.PREFERRED_SIZE))

.addContainerGap(323, Short.MAX_VALUE))

);

pack();

}

private int selectOnBoard(int x, int y) {

int[] bounds = (bonesOnTheDesk.get(0).getBounds());

if (x > bounds[0] && x < bounds[1] && y > bounds[2] && y < bounds[3]) {

return 0;

}

bounds = (bonesOnTheDesk.get(bonesOnTheDesk.size() - 1).getBounds());

if (x > bounds[0] && x < bounds[1] && y > bounds[2] && y < bounds[3]) {

return bonesOnTheDesk.size();

}

return -1;

}

// попытка взять кость игрока по данным координатам

private int selectBone(int x, int y) {

for (int i = 0; i < playersBones[currentPlayerIdx].size(); i++) {

Bone bone = playersBones[currentPlayerIdx].get(i);

int[] bounds = (bone.getBounds());

if (x > bounds[0] && x < bounds[1] && y > bounds[2] && y < bounds[3]) {

return i;

}

}

return -1;

}

private void exitForm(WindowEvent evt) {

System.exit(0);

}

private void formWindowOpened(WindowEvent evt) {

}

private void formWindowActivated(WindowEvent evt) {

}

private void formComponentShown(ComponentEvent evt) {

}

// инициализация костей и раздача их игрокам

private void initBones() {

ArrayList<Bone> bonesPool = new ArrayList<Bone>();

bonesPool.clear();

for (byte p = 0; p <= MAX_BONE_VALUE; p++) {

for (byte q = 0; q <= p; q++) {

bonesPool.add(new Bone(p, q));

}

}

for (int i = 0; i < PLAYERS_COUNT; i++) {

playersBones[i] = new ArrayList<Bone>();

}

bonesOnTheDesk = new ArrayList<Bone>();

for (int i = 0; i < MAX_BONES_COUNT; i++) {

for (int p = 0; p < PLAYERS_COUNT; p++) {

int k = (int) (Math.random() * bonesPool.size());

playersBones[p].add(bonesPool.get(k));

bonesPool.remove(k);

}

}

}

// то что мы делаем при старте

private void startButtonListener(ActionEvent evt) {

graphics.clearRect(0, 0, getWidth(), getHeight());

// Инициализируем пул костей и раздаем их между игроками

initBones();

// Размещаем кости игроков на экране

for (int p = 0; p < PLAYERS_COUNT; p++) {

for (int i = 0; i < MAX_BONES_COUNT; i++) {

Bone bone = playersBones[p].get(i);

int x = 0, y = 0;

int dx = 0, dy = 0;

switch (p) {

case 0:

x = this.getWidth() / 2 - Bone.width * 7;

y = this.getHeight() - Bone.width;

dx = (Bone.height + 10);

dy = 0;

bone.rotate((byte) 1, (byte) 0, graphics, backgroundColor);

break;

case 1:

x = Bone.width;

y = 120;

dx = 0;

dy = Bone.height + 10;

bone.rotate((byte) 0, (byte) 1, graphics, backgroundColor);

break;

case 2:

x = this.getWidth() / 2 - Bone.width * 7;

y = 30 + Bone.width;

dx = (Bone.height + 10);

dy = 0;

bone.rotate((byte) -1, (byte) 0, graphics, backgroundColor);

break;

case 3:

x = this.getWidth() - Bone.width;

y = 120;

dx = 0;

dy = Bone.height + 10;

bone.rotate((byte) 0, (byte) -1, graphics, backgroundColor);

break;

}

bone.moveTo(x + i * dx, y + i * dy, graphics, backgroundColor);

}

}

int idxOfFirstPlayingPlayer = -1;

for (int n = 1; n <= MAX_BONE_VALUE; n++) {

for (int p = 0; p < PLAYERS_COUNT; p++) {

for (int i = 0; i < playersBones[p].size(); i++) {

Bone bone = playersBones[p].get(i);

if (bone.points(0) == n && bone.points(1) == n) {

currentPlayerIdx = p;

idxOfFirstPlayingPlayer = i;

}

}

}

if (currentPlayerIdx >= 0) break;

}

int pause = 2000;

long t = System.currentTimeMillis();

do {

} while (System.currentTimeMillis() - t < pause);

Bone bone = playersBones[currentPlayerIdx].get(idxOfFirstPlayingPlayer);

bone.rotate(1, 0, graphics, backgroundColor);

bone.moveSliding(getWidth() / 2, getHeight() / 2, 500, graphics, backgroundColor);

bonesOnTheDesk.add(bone);

playersBones[currentPlayerIdx].remove(idxOfFirstPlayingPlayer);

currentPlayerIdx = (currentPlayerIdx + 1) % PLAYERS_COUNT;

updateAppTitle();

placeJ[0] = bone.getX();

placeJ[1] = bone.getX();

placeK[0] = bone.getY();

placeK[1] = bone.getY();

rotationJ[0] = -1;

rotationJ[1] = +1;

rotationK[0] = 0;

rotationK[1] = 0;

endPoints[0] = bone.points(0);

endPoints[1] = bone.points(1);

isChoosingBone = false;

doMove();

}

private synchronized void doMove() {

int x2, y2;

Bone bone = null;

int side = -1;

boolean isShouldReturn;

if (isChoosingBone) {

isChoosingBone = false;

isShouldReturn = false;

bone = playersBones[currentPlayerIdx].get(selectedIdx);

highlightBones(bone, false);

if (selectedOnBoard == -1) {

return;

} else {

bonesOnTheDesk.add(selectedOnBoard, bone);

playersBones[currentPlayerIdx].remove(selectedIdx);

side = (selectedOnBoard == 0) ? 0 : 1;

selected = false;

}

} else if (!hasMoves()) {

passesCount++;

currentPlayerIdx = (currentPlayerIdx + 1) % PLAYERS_COUNT;

getToolkit().beep();

updateAppTitle();

doMove();

return;

} else if (!selected) {

isShouldReturn = true;

} else {

bone = playersBones[currentPlayerIdx].get(selectedIdx);

isShouldReturn = true;

if ((endPoints[0] != endPoints[1]) && (bone.points(0) == endPoints[0] && bone.points(1) == endPoints[1]) || (bone.points(1) == endPoints[0] && bone.points(0) == endPoints[1])) {

highlightBones(bone, true);

isChoosingBone = true;

selected = false;

return;

}

for (side = 0; side <= 1; side++) {

if (bone.points(0) == endPoints[side] ||

bone.points(1) == endPoints[side]) {

if (side == 0) {

bonesOnTheDesk.add(0, bone);

} else {

bonesOnTheDesk.add(bonesOnTheDesk.size(), bone);

}

playersBones[currentPlayerIdx].remove(selectedIdx);

isShouldReturn = false;

break;

}

}

selected = false;

}

if (isShouldReturn) {

return;

}

boolean stop = false;

if (bone.points(0) == endPoints[side]) {

bone.rotate(+rotationJ[side], +rotationK[side], graphics, backgroundColor);

endPoints[side] = bone.points(1);

} else {

bone.rotate(-rotationJ[side], -rotationK[side], graphics, backgroundColor);

endPoints[side] = bone.points(0);

}

placeJ[side] += rotationJ[side] * Bone.height;

placeK[side] += rotationK[side] * Bone.height;

x2 = placeJ[side];

y2 = placeK[side];

if (rotationJ[side] == -1 && placeJ[side] < Bone.height * 3) {

rotationJ[side] = 0;

rotationK[side] = -1;

placeJ[side] -= Bone.width / 2;

placeK[side] += Bone.width / 2;

}

if (rotationK[side] == -1 && placeK[side] < Bone.height * 3) {

rotationJ[side] = +1;

rotationK[side] = 0;

placeJ[side] -= Bone.width / 2;

placeK[side] -= Bone.width / 2;

}

if (rotationJ[side] == +1 && placeJ[side] > getWidth() - Bone.height * 3) {

rotationJ[side] = 0;

rotationK[side] = +1;

placeJ[side] += Bone.width / 2;

placeK[side] -= Bone.width / 2;

}

if (rotationK[side] == +1 && placeK[side] > getHeight() / 2 * (side + 1) - Bone.height * 2) {

rotationJ[side] = -1;

rotationK[side] = 0;

placeJ[side] += Bone.width / 2;

placeK[side] += Bone.width / 2;

}

bone.moveSliding(x2, y2, 500, graphics, backgroundColor);

for (Bone aBonesOnTheDesk : bonesOnTheDesk) {

aBonesOnTheDesk.show(graphics);

}

for (int p = 0; p < PLAYERS_COUNT; p++) {

for (int i = 0; i < playersBones[p].size(); i++) {

playersBones[p].get(i).show(graphics);

}

}

passesCount = 0;

if (playersBones[currentPlayerIdx].size() == 0) {

stop = true;

}

if (passesCount == PLAYERS_COUNT) {

JOptionPane.showMessageDialog(this, "Рыба! Победил игрок :" + getWinnerName());

return;

} else if (stop) {

JOptionPane.showMessageDialog(this, "Победил игрок : " + ("Человек №" + (currentPlayerIdx + 1)));

return;

}

currentPlayerIdx = (currentPlayerIdx + 1) % PLAYERS_COUNT;

updateAppTitle();

doMove();

}

private void highlightBones(Bone bone, boolean isHighlight) {

Bone begin = bonesOnTheDesk.get(0);

Bone end = bonesOnTheDesk.get(bonesOnTheDesk.size() - 1);

if (isHighlight) {

bone.setColorMarked().show(graphics);

begin.setColorMarked().show(graphics);

end.setColorMarked().show(graphics);

} else {

bone.setColorUsual().show(graphics);

begin.setColorUsual().show(graphics);

end.setColorUsual().show(graphics);

}

}

private boolean hasMoves() {

for (int i = 0; i < playersBones[currentPlayerIdx].size(); i++) {

Bone bone = playersBones[currentPlayerIdx].get(i);

for (int side = 0; side <= 1; side++) {

if (bone.points(0) == endPoints[side] || bone.points(1) == endPoints[side]) {

return true;

}

}

}

return false;

}

private String getWinnerName() {

int winnerIdx = 0;

int min = 239239; // это число явно больше суммы всех цифр на костяшках

for (int p = 0; p < PLAYERS_COUNT; p++) {

int curMin = 0;

for (Bone bone : playersBones[p]) {

curMin += bone.points(0) + bone.points(1);

}

if (curMin < min) {

min = curMin;

winnerIdx = p;

}

}

return "Человек №" + (winnerIdx + 1);

}

private void stopButtonListener(ActionEvent evt) {

// do nothing

}

public static void main(String args[]) {

EventQueue.invokeLater(new Runnable() {

public void run() {

MainFrame frame = new MainFrame();

frame.setSize(800, 600);

frame.setLocation(100, 50);//?!

frame.setVisible(true);

}

});

}

}

Приложение 2.Тестовый пример

Для запуска игры нужно нажать кнопку «Начать»:

Далее реализуется игра. В игре участвуют 4 игрока, каждым из которых управляет пользователь, при этом в заголовке окна указывается тот из них, кто делает ход. Кости постепенно выкладываются в цепь:

Игра заканчивается, когда у одного из игроков не остается ни одной кости, или ни у кого из игроков нет подходящей:

В представленном примере у пользователя было наименьшее количество очков, именно поэтому он объявлен победителем. Ситуация «рыба» предусмотрена.

Размещено на Allbest.ru


Подобные документы

  • Характеристика библиотеки java.awt. Обработка событий управляющими компонентами и менеджерами размещения. Основные виды компонентов. Написание программы–калькулятора, реализующую графический интерфейс. Спецификация класса Calc и иерархия классов AWT.

    методичка [643,8 K], добавлен 30.06.2009

  • Особенности разработки программы в среде Delphi 7, которая предлагает случайно вычислить одну из последовательностей "рыбы" в игре Домино. Особенности создания интерфейсов для рабочей программы. Формальная постановка задачи. Руководство пользователя.

    курсовая работа [295,1 K], добавлен 19.10.2010

  • Анализ целевой аудитории. Функциональные характеристики пользовательского приложения. Разработка алгоритмов и интерфейса программного продукта, функций рабочей области. Написание скриптов на языке C#. Тестирование программы методом чёрного ящика.

    дипломная работа [1,5 M], добавлен 09.11.2016

  • Рассмотрение игр, схожих по жанру и модели распространения с разрабатываемым приложением. Выбор среды разработки и сторонних библиотек. Проектирование интерфейса и подготовка графических материалов приложения. Особенности введения в игру микротрансакций.

    дипломная работа [3,1 M], добавлен 18.11.2017

  • Диаграмма консольного приложения табулирования функции. Отличие консольного приложения и приложения и GUI. Диаграмма классов для JFrameи JPanel. Создание простейшего фрейма в Java. Компоновка элементов интерфейса внутри фрейма. Цикл обработки событий.

    лекция [693,8 K], добавлен 01.05.2014

  • Разработка эскизного и технического проектов программы, моделирующей игру "Кости". Постановка задачи, описание алгоритма; написание программы, организация входных и выходных данных; выбор программных средств; спецификация, текст, условия выполнения.

    курсовая работа [93,8 K], добавлен 11.02.2012

  • Методика и основные этапы создания программы, взаимодействующей с пользователем посредствам графического интерфейса и выполняющей помехоустойчивое кодирование информации, ее цели. Алгоритм работы программы, отладка и проверка ее работоспособности.

    курсовая работа [43,1 K], добавлен 12.05.2013

  • Структура организации графического интерфейса, объявление и создание слушателей событий с помощью анонимных классов. Представление данных для таблицы – класс AbstractTableModel. Визуализация ячеек таблицы. Два основных типа потоков ввода-вывода в Java.

    лекция [685,3 K], добавлен 01.05.2014

  • Обобщенная структура и принципы функционирования экспертных систем. Выбор модели представления знаний. Разработка логического блока программы и графического пользовательского интерфейса. Текст программы и экспериментальная оценка результатов работы.

    дипломная работа [2,4 M], добавлен 06.03.2013

  • Изучение особенностей растровых и векторных графических редакторов. Создание графического редактора: выбор языка программирования, разработка структуры программы и алгоритма работы. Описание интерфейса программы. Руководство программиста и пользователя.

    курсовая работа [1,3 M], добавлен 28.07.2013

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.